2009-12-18 2 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) не является id записи, содержащей MAX(invoice_date) (3295), это 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, попытайтесь найти строка i2 с тем же invoice_id и больший срок. Если ни один не найден (т.е. i2 все нули из-за внешнего соединения), то i1 должен быть строкой с наибольшей датой для ее invoice_id.

Это решение с использованием соединения имеет тенденцию работать лучше для MySQL, что является слабым при оптимизации как GROUP BY, так и подзапросов.

+0

Это, кажется, работает как хотелось бы, однако это невероятно медленно. Может ли это быть лучшим решением, чем использование GROUP BY на MySQL? – rswolff

+0

Попробуйте оба и посмотрите. Не забудьте проанализировать оба запроса с помощью команды «EXPLAIN». –

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 

или лучше, если ваш идентификатор ваш первичный ключ и постоянно растет

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