2011-09-04 70 views
1

我有一個數據表是這樣的:只選擇最新的分組項

+-----------+-------+------+----------+ 
| 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 

,然後使用結果集來過濾第二選擇,但如何?也許有一個聰明的方式來做到這一點沒有一個子選擇?

+0

似乎很相似,這所以問題:http://stackoverflow.com/questions/2657482/sql-find-the-max-record-per-group也許看看那一個。 – itsmatt

回答

2

據我所知,次選是最好的選擇,如下所示:

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); 
1
SELECT * FROM 
(SELECT * FROM mytable ORDER BY timestamp DESC) AS T1 
GROUP BY event; 
+0

+1如果這個工程。你會不會只收回事件ID? –

+0

嗨本 - 它沒有:)我已經更新了我的答案。排序後您無法使用GROUP BY,因此需要使用子查詢。 –

+0

也有作品。但我想知道這是否比Ben的解決方案慢。我們假設該表有數百萬條記錄。 Ben的答案中的子選擇只是選擇分組的最大時間戳(讓我們假設它的索引是正確的),而你的子選擇在第一次選擇時選擇數據庫的所有行,然後將它們分組在一秒鐘內。那麼,也許數據庫優化它,所以沒有什麼區別,但我現在與本的解決方案。 – kayahr

2

你可以使用一個內連接作爲一個過濾器:

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 
0
SELECT e2.* 
FROM  events e 
JOIN  events e2 ON e2.event = e.event AND e2.timestamp = MAX(e2.timestamp) 
GROUP BY e.id