2009-12-18 43 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