Выбрать только самые новые сгруппированные записи - PullRequest
1 голос
/ 04 сентября 2011

У меня есть таблица с такими данными:

+-----------+-------+------+----------+
| timestamp | event | data | moreData |
+-----------+-------+------+----------+
| 100000000 |     1 |   10 |       20 |
| 100000001 |     1 |   15 |       10 |
| 100000002 |     1 |   30 |       30 |
| 100000003 |     1 |    5 |       50 |
| 100000004 |     2 |  110 |      120 |
| 100000005 |     2 |  115 |      110 |
| 100000006 |     2 |  130 |      130 |
| 100000007 |     2 |   15 |      150 |
+-----------+-------+------+----------+

Теперь я хочу выбрать только самые новые строки для каждого события. Итак, в конце я хочу получить этот набор результатов:

+-----------+-------+------+----------+
| timestamp | event | data | moreData |
+-----------+-------+------+----------+
| 100000003 |     1 |    5 |       50 |
| 100000007 |     2 |   15 |      150 |
+-----------+-------+------+----------+

Пока я не смог этого сделать. В MySQL я могу использовать «событие GROUP BY», но затем я получаю некоторую случайную строку из базы данных, а не самую новую. ORDER BY не помогает, потому что группировка выполняется перед заказом. Использование агрегации, такой как MAX (отметка времени) при группировке по событию, также не помогает, потому что отметка времени является самой новой, но «данные» и «moreData» все еще из какой-то другой случайной строки.

Полагаю, мне нужно сделать дополнительный выбор, поэтому я должен сначала получить последнюю метку времени, например:

SELECT MAX(timestamp), event FROM mytable GROUP BY event

и затем использовать набор результатов для фильтрации второго SELECT, но как? А может быть, есть умный способ сделать это без суб-выбора?

Ответы [ 4 ]

2 голосов
/ 04 сентября 2011

AFAIK, суб-выбор является вашим лучшим вариантом, следующим образом:

SELECT * 
FROM mytable mt 
    JOIN ( SELECT MAX(timestamp) as max, event 
           FROM mytable 
           GROUP BY event) m_mt 
    ON (mt.timestamp = m_mt.max AND mt.event = m_mt.event);
2 голосов
/ 04 сентября 2011

Вы можете использовать внутреннее объединение в качестве фильтра:

select  *
from    events e1
join    (
        select  event
        ,       max(timestamp) as maxtimestamp
        from    events
        group by
                event
        ) e2
on      e1.event = e2.event
        and e1.tiemstamp = e2.maxtimestamp 
1 голос
/ 04 сентября 2011
SELECT * FROM 
(SELECT * FROM mytable ORDER BY timestamp DESC) AS T1 
GROUP BY event;
0 голосов
/ 04 сентября 2011
SELECT   e2.*
FROM     events e
JOIN     events e2 ON e2.event = e.event AND e2.timestamp = MAX(e2.timestamp)
GROUP BY e.id
...