[英]MYSQL: Retrievieng the last record from each group and combining with the data of another table
有一个购买表,其中包含有关产品的信息。 这将为购买的每个单独产品在 tStockMP 表中生成一行或多行。
现在,我需要显示每个库存产品的表格信息。 由于 purchase 表包含更改的历史记录,因此在 tPurchases 表中按 purchase_id 分组时,该信息位于最高的 keyid 中。
我提供了一个完整的脚本,这里有描述我的问题的示例数据。
DROP TABLE IF EXISTS tPurchases;
DROP TABLE IF EXISTS tStockMP;
-- The purchase table
CREATE TABLE tPurchases (
keyid INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
brand VARCHAR(255),
model VARCHAR(255),
purchase_id INT
);
INSERT INTO tPurchases (brand,model,purchase_id) VALUES ("Hp","note1",23);
INSERT INTO tPurchases (brand,model,purchase_id) VALUES ("Lg","IPSLED",45);
INSERT INTO tPurchases (brand,model,purchase_id) VALUES ("Hp","notE1",23);
INSERT INTO tPurchases (brand,model,purchase_id) VALUES ("Bx","BOX",56);
INSERT INTO tPurchases (brand,model,purchase_id) VALUES ("LG","IPSLED",45);
INSERT INTO tPurchases (brand,model,purchase_id) VALUES ("HP","NOTE1",23);
-- The Stock MP Table
CREATE TABLE tStockMP (
keyid INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
purchase_id INT,
status TINYINT
);
INSERT INTO tStockMP (purchase_id,status) VALUES (23,1);
INSERT INTO tStockMP (purchase_id,status) VALUES (23,1);
INSERT INTO tStockMP (purchase_id,status) VALUES (23,0);
INSERT INTO tStockMP (purchase_id,status) VALUES (45,0);
INSERT INTO tStockMP (purchase_id,status) VALUES (56,1);
INSERT INTO tStockMP (purchase_id,status) VALUES (56,1);
INSERT INTO tStockMP (purchase_id,status) VALUES (56,0);
-- Example data
--
-- tPurchases table
-- keyid brand model purchase_id
-- 0 Hp note1 23
-- 1 Lg IPSLED 45
-- 2 Hp notE1 23
-- 3 Bx BOX 56
-- 4 LG IPSLED 45
-- 5 HP NOTE1 23
--
--
-- tStockMP table.
-- purchase_id status
-- 23 1
-- 23 1
-- 23 0
-- 45 0
-- 56 1
-- 56 1
-- 56 0
--
--
-- Expected result
--
-- purchase_id status brand model
-- 23 1 HP NOTE1
-- 23 1 HP NOTE1
-- 23 0 HP NOTE1
-- 45 0 LG IPSLED
-- 56 1 Bx BOX
-- 56 1 Bx BOX
-- 56 0 Bx BOX
SELECT s.keyid, s.purchase_id, s.status, p.brand, p.model, p.keyid AS purkeyid
FROM tStockMP AS s, tPurchases AS p
WHERE s.purchase_id = p.purchase_id;
-- +-------+-------------+--------+-------+--------+----------+
-- | keyid | purchase_id | status | brand | model | purkeyid |
-- +-------+-------------+--------+-------+--------+----------+
-- | 1 | 23 | 1 | Hp | note1 | 1 |
-- | 1 | 23 | 1 | Hp | notE1 | 3 |
-- | 1 | 23 | 1 | HP | NOTE1 | 6 |-> *
-- | 2 | 23 | 1 | Hp | note1 | 1 |
-- | 2 | 23 | 1 | Hp | notE1 | 3 |
-- | 2 | 23 | 1 | HP | NOTE1 | 6 |-> *
-- | 3 | 23 | 0 | Hp | note1 | 1 |
-- | 3 | 23 | 0 | Hp | notE1 | 3 |
-- | 3 | 23 | 0 | HP | NOTE1 | 6 |-> *
-- | 4 | 45 | 0 | Lg | IPSLED | 2 |
-- | 4 | 45 | 0 | LG | IPSLED | 5 |-> *
-- | 5 | 56 | 1 | Bx | BOX | 4 |-> *
-- | 6 | 56 | 1 | Bx | BOX | 4 |-> *
-- | 7 | 56 | 0 | Bx | BOX | 4 |-> *
-- +-------+-------------+--------+-------+--------+----------+
我需要“过滤”结果,以便只有 * 行保留在最终查询中,以免我需要手动完成。 但我不知道如何修改我的查询并实现这一点。
如果您的数据库支持 window 函数,您可以使用ROW_NUMBER()
来识别每个组的“最新”记录,并使用该信息来过滤数据集:
SELECT *
FROM (
SELECT
s.keyid,
s.purchase_id,
s.status,
p.brand,
p.model,
p.keyid AS purkeyid,
ROW_NUMBER() OVER(PARTITION BY s.keyid ORDER BY p.keyid DESC) rn
FROM tStockMP AS s
INNER JOIN tPurchases AS p ON p.purchase_id = s.purchase_id
) t
WHERE rn = 1
切勿在FROM
子句中使用逗号。 我典型的解决方案是使用相关子查询:
SELECT s.keyid, s.purchase_id, s.status, p.brand, p.model, p.keyid AS purkeyid
FROM tStockMP s JOIN
tPurchases p
ON s.purchase_id = p.purchase_id
WHERE p.keyid = (SELECT MAX(p2.keyid)
FROM tPurchases p2
WHERE p2.purchase_id = p.purchase_id
);
使用tPurchases(purchase_id, keyid)
上的索引,这通常具有最佳性能。
如果我使用 window 函数来解决这个问题,我会将其表述为:
SELECT s.keyid, s.purchase_id, s.status, p.brand, p.model, p.keyid AS purkeyid
FROM tStockMP s JOIN
(SELECT p.*,
ROW_NUMBER() OVER (PARTITION BY purchase_id ORDER BY keyid DESC) as seqnum
FROM tPurchases p
) p
ON s.purchase_id = p.purchase_id
WHERE seqnum = 1;
GMB 有另一种方法。 如果您有大量数据,比较这两种方法的性能会很有趣。 对于所有比较,我建议使用与上述相同的索引。
首先在tPurchases
中使用NOT EXISTS
以仅获取具有最大keyid
的行,然后加入tStockMP
:
SELECT s.keyid, s.purchase_id, s.status, t.brand, t.model, t.keyid AS purkeyid
FROM tStockMP AS s
INNER JOIN (
SELECT p.* FROM tPurchases AS p
WHERE NOT EXISTS (
SELECT 1 FROM tPurchases
WHERE purchase_id = p.purchase_id AND keyid > p.keyid
)
) AS t ON t.purchase_id = s.purchase_id
请参阅演示。
结果:
| keyid | purchase_id | status | brand | model | purkeyid |
| ----- | ----------- | ------ | ----- | ------ | -------- |
| 1 | 23 | 1 | HP | NOTE1 | 6 |
| 2 | 23 | 1 | HP | NOTE1 | 6 |
| 3 | 23 | 0 | HP | NOTE1 | 6 |
| 4 | 45 | 0 | LG | IPSLED | 5 |
| 5 | 56 | 1 | Bx | BOX | 4 |
| 6 | 56 | 1 | Bx | BOX | 4 |
| 7 | 56 | 0 | Bx | BOX | 4 |
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.