ske*_*rit 1 mysql sql join greatest-n-per-group
我的数据库中有库存数量信息.
1表,"stock",保存productid(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
但它没有用
SHOW CREATE TABLE库存:
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
SHOW CREATE TABLE stockfile:
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上看到的经常被问到的" 每组最大 "问题的一个例子.按照该标记查看其他类似解决方案.
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;
Run Code Online (Sandbox Code Playgroud)
如果有多行stockfile
具有最大日期,您将在结果集中获取它们.要解决此问题,您必须在连接中添加一些打破平局条件f2
.
感谢您添加CREATE TABLE
信息.当你提出SQL问题时,这非常有用.
我从AUTO_INCREMENT
表格中看到你有315k行stock
,只有265行stockfile
.您的stockfile
表是关系中的父表,stock
表是子表,其中一列stockfileid
引用了主键stockfile
.
所以你原来的问题是误导性的.您想要最新的行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;
Run Code Online (Sandbox Code Playgroud)
我假设你想要"最新"是相对的touchdate
,所以如果你想使用它creationdate
,你可以进行编辑.
我在连接中添加了一个术语,以便它解决关系.我知道你说日期"实际上是独一无二的",但俗话说" 下周二百万分之一 ".
好的,我想我明白你现在要做的是什么.您需要最新的每行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;
Run Code Online (Sandbox Code Playgroud)
这会自行连接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);
Run Code Online (Sandbox Code Playgroud)
我建议使用EXPLAIN
分析没有索引的查询,然后一次创建一个索引并重新分析,EXPLAIN
以查看哪一个给出最直接的好处.
归档时间: |
|
查看次数: |
2780 次 |
最近记录: |