使用MAX()和GROUP BY时如何选择整个记录

时间:2009-12-18 21:59:54

标签: sql mysql greatest-n-per-group

使用MYSQL我想重构以下SELECT语句以返回包含最新invoice_date整个记录:

> 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)不是包含id的记录的MAX(invoice_date)(3295)它是初始查询中第一条记录的id

如何重构此查询以向我提供包含MAX(invoice_date)整个记录?

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

5 个答案:

答案 0 :(得分:7)

这是经常重复的“每组最大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,尝试查找具有相同i2和更长日期的行invoice_id。如果没有找到(即i2因外部联接而全部为空),则i1必须是invoice_id日期最长的行。

使用join的此解决方案往往更适合MySQL,在优化GROUP BY和子查询时,它很弱。

答案 1 :(得分: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

答案 2 :(得分:2)

几乎就像你用英语说的那样

“获取最新发票日期的发票”

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

但我认为你的架构出了问题。由于存在多个具有相同Invoice_Id的行,因此这看起来像发票明细或发票行项目表(不是发票表)。如果是这样,同一发票中的每个行项目如何具有不同的InvoiceDates“?如果这些不同,则它们不是发票日期,它们是发票明细日期,(无论这意味着什么),并且应该标记为如此。< / p>

答案 3 :(得分: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

答案 4 :(得分: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