我的数据库中有库存数量信息。
1 个表,“stock”,包含产品 ID (sku) 及其来源的数量和文件名。
另一个表“stockfile”包含所有已处理的文件名和日期。
现在我需要获取所有产品及其最新库存数量值。
这给了我所有产品的所有库存数量(产生 300.000 条记录)
SELECT stock.stockid, stock.sku, stock.quantity, stockfile.filename, stockfile.date
FROM stock
INNER JOIN stockfile ON stock.stockfileid = stockfile.stockfileid
ORDER BYstock
.sku
ASC
我已经试过了:
SELECT * FROM stock
INNER JOIN stockfile ON stock.stockfileid = stockfile.stockfileid
GROUP BY sku
HAVING stockfile.date = MAX( stockfile.date )
ORDER BYstock
.sku
ASC
但是没有效果
显示创建表库存:
CREATE TABLE
stock
(
stockid
bigint(20) NOT NULL AUTO_INCREMENT,
sku
char(25) NOT NULL,
quantity
int(5) NOT NULL,
creationdate
datetime NOT NULL,
stockfileid
smallint(5) unsigned NOT NULL,
touchdate
datetime NOT NULL,
PRIMARY KEY (stockid
)
) ENGINE=MyISAM AUTO_INCREMENT=315169 DEFAULT CHARSET=latin1
显示创建表库存文件:
CREATE TABLE
stockfile
(
stockfileid
smallint(5) unsigned NOT NULL AUTO_INCREMENT,
filename
varchar(25) NOT NULL,
creationdate
datetime DEFAULT NULL,
touchdate
datetime DEFAULT NULL,
date
datetime DEFAULT NULL,
begindate
datetime DEFAULT NULL,
enddate
datetime DEFAULT NULL,
PRIMARY KEY (stockfileid
)
) ENGINE=MyISAM AUTO_INCREMENT=265 DEFAULT CHARSET=latin1
最佳答案
这是我们每周在 StackOverflow 上看到的常见问题“greatest-n-per-group”的示例。按照该标签查看其他类似的解决方案。
SELECT s.*, f1.*
FROM stock s
INNER JOIN stockfile f1
ON (s.stockfileid = f1.stockfileid)
LEFT OUTER JOIN stockfile f2
ON (s.stockfileid = f2.stockfileid AND f1.date < f2.date)
WHERE f2.stockfileid IS NULL;
如果 stockfile
中有多行具有最大日期,您将在结果集中同时获得它们。要解决此问题,您必须在 f2
上的连接中添加一些决胜条件。
感谢您添加 CREATE TABLE
信息。这在您询问 SQL 问题时非常有用。
我从 AUTO_INCREMENT
表选项中看到您在 stock
中有 315k 行,而在 stockfile
中只有 265 行。您的 stockfile
表是关系中的父表,stock
表是子表,其中有一列 stockfileid
引用 库存文件
。
所以您最初的问题具有误导性。您需要 stock
中的最新行,而不是 stockfile
中的最新行。
SELECT f.*, s1.*
FROM stockfile f
INNER JOIN stock s1
ON (f.stockfileid = s1.stockfileid)
LEFT OUTER JOIN stock s2
ON (f.stockfileid = s2.stockfileid AND (s1.touchdate < s2.touchdate
OR s1.touchdate = s2.touchdate AND s1.stockid < s2.stockid))
WHERE s2.stockid IS NULL;
我假设您希望“最新”相对于 touchdate
,因此如果您想改用 creationdate
,您可以进行编辑。
我已经在连接中添加了一个术语,以便它解析关系。我知道您说过日期“实际上是独一无二的”,但俗话说,“one in a million is next Tuesday”。
好的,我想我明白你现在想做什么了。您需要每个 sku
的最新行,但是用来比较它们的 date
位于引用的表 stockfile
中。
SELECT s1.*, f1.*
FROM stock s1
JOIN stockfile f1 ON (s1.stockfileid = f1.stockfileid)
LEFT OUTER JOIN (stock s2 JOIN stockfile f2 ON (s2.stockfileid = f2.stockfileid))
ON (s1.sku = s2.sku AND (f1.date < f2.date OR f1.date = f2.date AND f1.stockfileid < f2.stockfileid))
WHERE s2.sku IS NULL;
这会自连接 stock
到自身,寻找具有相同 sku
和更新的 date
的行。如果未找到任何内容,则 s1
包含其 sku
的最新行。 stock
的每个实例都必须加入其 stockfile
以获取 date
。
关于优化的评论:我很难测试,因为我没有填充与您匹配的数据的表,但我猜您应该有以下索引:
CREATE INDEX stock_sku ON stock(sku);
CREATE INDEX stock_stockfileid ON stock(stockfileid);
CREATE INDEX stockfile_date ON stockfile(date);
我建议使用 EXPLAIN
来分析没有索引的查询,然后一次创建一个索引并使用 EXPLAIN
重新分析以查看哪个给出最直接的好处。
关于sql - 从连接的 MySQL 表中选择最新条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1918827/