Sql 将MAX()与GROUP BY一起使用时,如何选择整个记录
我想使用MYSQL重构以下Sql 将MAX()与GROUP BY一起使用时,如何选择整个记录,sql,mysql,greatest-n-per-group,Sql,Mysql,Greatest N Per Group,我想使用MYSQL重构以下SELECT语句,以返回包含最新invoice\u日期的整个记录: 使用MAX()聚合函数和GROUP BY子句可以部分实现以下目的: > SELECT id, invoice_id, max(invoice_date) FROM invoice_items WHERE invoice_id = 1047 GROUP BY invoice_id id invoice_id invoice_date --------------------
SELECT
语句,以返回包含最新invoice\u日期的整个记录:
使用MAX()聚合函数和GROUP BY子句可以部分实现以下目的:
> SELECT id, invoice_id, max(invoice_date)
FROM invoice_items
WHERE invoice_id = 1047
GROUP BY invoice_id
id invoice_id invoice_date
-----------------------------------
3235 1047 2009-12-15 16:00:00
请注意,查询似乎正确获取了MAX(invoice\u date)
,但返回的id
(3235)不是包含MAX(invoice\u date)
(3295)的记录的id
,而是初始查询中第一条记录的id
如何重构此查询以提供包含MAX(发票日期)
的整个记录
解决方案必须使用GROUP BY子句,因为我需要为每个发票获取最新的invoice\u日期。我假设由于表名是invoice\u items,因此给定发票将有多行,因此您可能应该使用如下内容:
SELECT * FROM invoice_items
WHERE invoice_date IN (SELECT MAX(invoice_date) FROM invoice_items)
如果您不担心两个记录具有相同的发票日期,您可以这样做:
SELECT * FROM invoice_items
ORDER BY invoice_date DESC
LIMIT 1
如果你的id是你的主键并且一直在增长,那就更好了
SELECT *
FROM invoice_items
WHERE lot = 1047
ORDER BY id desc LIMIT 1
和你用英语说的差不多
“给我最新发票日期的发票”
但我认为你的模式有问题。由于有多行具有相同的发票Id,因此看起来像是发票明细表或发票行项目表(而不是发票表)。如果是这样,那么同一发票中的每一行项目怎么会有不同的发票日期呢?如果这些不同,那么它们就不是发票日期,而是发票详细日期(不管是什么意思),应该这样标记。这是经常重复出现的“每组最大n个”问题
下面是我将如何在MySQL中解决它:
SELECT i1.*
FROM invoice_items i1
LEFT OUTER JOIN invoice_items i2
ON (i1.invoice_id = i2.invoice_id AND i1.invoice_date < i2.invoice_date)
WHERE i2.invoice_id IS NULL;
选择i1*
来自发票项目i1
左外连接发票\u项目i2
ON(i1.发票id=i2.发票id和i1.发票日期
说明:对于每一行i1
,尝试查找具有相同invoice\u id
和更大日期的行i2
。如果未找到任何行(即i2
由于外部联接而全部为空),则i1
必须是其invoice\u id
日期最大的行
这种使用join的解决方案更适合MySQL,在优化分组方式和子查询时,MySQL的性能很差。以下是我的尝试:
SELECT t1.*
FROM INVOICE_ITEMS t1,
(SELECT INVOICE_ID, MAX(INVOICE_DATE) as invoice_date2
FROM INVOICE_ITEMS
GROUP BY INVOICE_ID) t2
WHERE t1.invoice_id = t2.invoice_id
AND t1.invoice_date = t2.invoice_date2
这似乎可以正常工作,但速度非常慢。这真的比在MySQL上使用GROUP BY更好吗?两种方法都试试看。别忘了用解释分析这两个查询。
Select * From invoice_items
Where invoice_date =
(Select Max(invoice_date)
From invoice_items)
SELECT i1.*
FROM invoice_items i1
LEFT OUTER JOIN invoice_items i2
ON (i1.invoice_id = i2.invoice_id AND i1.invoice_date < i2.invoice_date)
WHERE i2.invoice_id IS NULL;
SELECT t1.*
FROM INVOICE_ITEMS t1,
(SELECT INVOICE_ID, MAX(INVOICE_DATE) as invoice_date2
FROM INVOICE_ITEMS
GROUP BY INVOICE_ID) t2
WHERE t1.invoice_id = t2.invoice_id
AND t1.invoice_date = t2.invoice_date2