2009-12-18 46 views
3

使用MySQL,我想重构以下SELECT语句返回包含最新invoice_date整个记录:如何选择整个记录使用MAX()当与GROUP BY

> SELECT id, invoice, invoice_date 
    FROM invoice_items 
    WHERE lot = 1047 

id invoice_id invoice_date 
----------------------------------- 
3235 1047   2009-12-15 11:40:00 
3295 1047   2009-12-15 16:00:00 
3311 1047   2009-12-15 09:30:00 
3340 1047   2009-12-15 13:50:00 

使用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_date),但id返回的(3235)不是包含MAX(invoice_date)(3295)的记录的id,它是初始查询中第一条记录的id

如何重构此查询以给我包含MAX(invoice_date)的整个记录​​

该解决方案必须使用GROUP BY子句,因为我需要为每个发票获取最新的invoice_date

回答

7

这是经常重复的“最伟大的正每组”问题

这是我会怎么解决它在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,试图找到行i2invoice_id和更大的日期。如果没有发现(即i2是所有空值因为外连接),那么i1必须是其invoice_id的最大日期。

这个使用连接的解决方案往往更适用于MySQL,这在优化GROUP BY和子查询时很弱。

+0

这似乎需要工作但它是慢得令人难以置信。这真的可以比在MySQL上使用GROUP BY更好的解决方案吗? – rswolff 2009-12-18 22:59:56

+0

试试看看。不要忘记用'EXPLAIN'分析两个查询。 – 2009-12-18 23:12:55

3

我假设,因为表名是invoice_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 
0
SELECT * 
FROM invoice_items 
WHERE lot = 1047 
ORDER BY invoice_date desc LIMIT 1 

或者更好,如果你的ID是你的主键,并一直在成长

SELECT * 
FROM invoice_items 
WHERE lot = 1047 
ORDER BY id desc LIMIT 1 
2

几乎正是你会说英语

的方式“给我用最新的发票日期发票”

Select * From invoice_items 
Where invoice_date = 
    (Select Max(invoice_date) 
    From invoice_items) 

但什么是错在你的模式,我认为。由于有多个具有相同Invoice_Id的行,因此它看起来像是发票明细或发票行项目表(不是发票表)。如果是这样,同一发票中的每个行项目如何具有不同的发票日期“?如果这些不同,那么它们不是发票日期,它们是发票明细日期(不管是什么意思)并且应该被标记为这样..

2

这里是我的尝试:

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