1

我的数据库中有库存数量信息。
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 BY stockskuASC

我已经尝试过了:

SELECT * FROM stock
INNER JOIN stockfile ON stock.stockfileid = stockfile.stockfileid
GROUP BY sku
HAVING stockfile.date = MAX( stockfile.date )
ORDER BY stockskuASC

但它没有用

显示创建表库存:

CREATE TABLE stock(
stockidbigint(20) NOT NULL AUTO_INCREMENT,
skuchar(25) NOT NULL,
quantityint(5) NOT NULL,
creationdatedatetime NOT NULL,
stockfileidsmallint(5) unsigned NOT NULL,
touchdatedatetime NOT NULL,
PRIMARY KEY ( stockid)
) ENGINE=MyISAM AUTO_INCREMENT =315169 默认字符集=latin1

显示创建表库存文件:

CREATE TABLE stockfile(
stockfileidsmallint(5) unsigned NOT NULL AUTO_INCREMENT,
filenamevarchar(25) NOT NULL,
creationdatedatetime DEFAULT NULL,
touchdatedatetime DEFAULT NULL,
datedatetime DEFAULT NULL,
begindatedatetime DEFAULT NULL,
enddatedatetime DEFAULT NULL,
PRIMARY KEY ( stockfileid)
) ENGINE=MyISAM AUTO_INCREMENT=265默认字符集=latin1

4

4 回答 4

6

这是我们每周在 StackOverflow 上看到的经常被问到的“每组最大 n ”问题的一个示例。按照该标签查看其他类似的解决方案。

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具有最大日期,您将在结果集中同时获得它们。要解决这个问题,您必须在 join on 中添加一些决胜局条件f2


感谢您添加CREATE TABLE信息。这在您提出 SQL 问题时非常有用。

我从AUTO_INCREMENT表选项中看到您有 315k 行,stockstockfile. 您的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;

我假设您希望“最新”相对于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;

这会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以查看哪一个提供最直接的好处。

于 2009-12-17T01:32:14.163 回答
2

采用:

SELECT DISTINCT s.stockid, 
       s.sku, 
       s.quantity, 
       sf.filename, 
       sf.date
  FROM STOCK s
  JOIN STOCKFILE sf ON sf.stockfileid = s.stockfileid
  JOIN (SELECT t.stockfileid,
               MAX(t.date) 'max_date'
          FROM STOCKFILE t
      GROUP BY t.stockfileid) x ON x.stockfileid = sf.stockfileid
                               AND x.max_date = sf.date
于 2009-12-17T01:06:52.177 回答
0

有两种常见的方法可以完成此操作:子查询或自联接。

请参阅MySQL 站点上选择分组最大值的示例。

编辑,使用子查询的示例:

SELECT stock.stockid, stock.sku, stock.quantity,
       stockfile.filename, stockfile.date
FROM stock
INNER JOIN stockfile ON stock.stockfileid = stockfile.stockfileid
WHERE stockfile.date = (SELECT MAX(date) FROM stockfile);
于 2009-12-17T01:04:08.390 回答
0
select *
from   stock
where  stockfileid in (
           select top 1 stockfileid
           from   stockfile
           order by date desc
       )
于 2009-12-17T01:04:41.820 回答