2012-06-12 81 views
31

比方說,我有一個名爲messages與列的表:如何使用GROUP BY獲取每個組中的最新記錄?

id | from_id | to_id | subject | message | timestamp 

我想從每個用戶得到的最新消息而已,就像你會在你的Facebook收件箱中看到你深入到實際的線程之前。

該查詢似乎讓我接近結果,我需要:

SELECT * FROM messages GROUP BY from_id 

但是查詢是給我的每一個用戶,而不是最新的最早的消息。

我無法弄清楚這一點。

+0

甚至還有一個更好的解決這個問題[這裏](http://stackoverflow.com/questions/1313120/retrieving-the-last-記錄在每個組) –

回答

74

你應該找出各組(子查詢)最後timestamp值,然後加入這個子查詢表 -

SELECT t1.* FROM messages t1 
    JOIN (SELECT from_id, MAX(timestamp) timestamp FROM messages GROUP BY from_id) t2 
    ON t1.from_id = t2.from_id AND t1.timestamp = t2.timestamp; 
+4

+1一個常見的問題,但非常感謝你不使用允許選擇列中的列不在組中的MySQL功能! – GarethD

+0

謝謝你太多了!我能夠毫無問題地加入附加表格。這樣一個好方法。 – user1019144

+0

這只是完美的。 – enchance

-4

您需要訂購它們。

SELECT * FROM messages GROUP BY from_id ORDER BY timestamp DESC LIMIT 1

+0

選擇頂部(1)* .... – BumbleB2na

+0

@ BumbleB2na'LIMIT 1'你的意思是? – Li0liQ

+0

現在你會得到所有消息的最後一條消息,你需要一個where條件 – jcho360

1

這是一個標準的問題。

請注意,MySQL允許您省略GROUP BY子句中的列,而標準SQL不支持這些列,但在使用MySQL設施時通常不會得到確定性結果。

SELECT * 
    FROM Messages AS M 
    JOIN (SELECT To_ID, From_ID, MAX(TimeStamp) AS Most_Recent 
      FROM Messages 
     WHERE To_ID = 12345678 
     GROUP BY From_ID 
     ) AS R 
    ON R.To_ID = M.To_ID AND R.From_ID = M.From_ID AND R.Most_Recent = M.TimeStamp 
WHERE M.To_ID = 12345678 

我已經添加在To_ID過濾器來匹配你很可能有。查詢將無法使用,但通常會返回更多數據。不應該在嵌套查詢和外部查詢中聲明條件(優化器應該自動將條件降低),但是如圖所示重複條件不會造成任何影響。

+0

最新的標準SQL允許您省略GROUP BY「,並將它們包含在SELECT或HAVING子句中,前提是它們在功能上依賴於GROUP BY組合,因此只會返回確定性結果。 (MySQL當然沒有這樣的檢查。) –

+0

@ypercube不知道這是否是這個地方,但是你有沒有這方面的好鏈接。我無法理解如何選擇不在組中的列可以通過依賴組中的項來變得確定,通過使用order by,我可以看到使它成爲非確定性的唯一方式。然而,看例子可能有助於解決問題。謝謝 – GarethD

+0

'GROUP BY pk'就是一個簡單的例子。我的答案[這裏](http://stackoverflow.com/questions/7594865/why-does-mysql-add-a-feature-that-c​​onflicts-with-sql-standards/7596265#7596265)有鏈接(副本的)標準。 –

2

就補充什麼Devart說,下面的代碼不排序依據的問題:

SELECT t1.* FROM messages t1 
    JOIN (SELECT from_id, MAX(timestamp) timestamp FROM messages GROUP BY from_id) t2 
    ON t1.from_id = t2.from_id AND t1.timestamp = t2.timestamp; 

的「GROUP BY」子句必須在主查詢,因爲我們需要先重新排序「源」以得到所需要的 「分組」 這麼:

SELECT t1.* FROM messages t1 
    JOIN (SELECT from_id, MAX(timestamp) timestamp FROM messages ORDER BY timestamp DESC) t2 
    ON t1.from_id = t2.from_id AND t1.timestamp = t2.timestamp GROUP BY t2.timestamp; 

問候,

12

試試這個

對於每Form_id
SELECT * FROM messages where id in (SELECT max(id) FROM messages GROUP BY from_id) order by id desc 
+3

雖然這段代碼可能會回答這個問題,但最好包含一些_context_,解釋_how_它的工作原理和_when_使用它。從長遠來看,僅有代碼的答案是沒有用的。 –

+0

「SELECT max(id)FROM messages GROUP BY from_id」這個內部查詢,它首先按用戶分組記錄/消息(from_id),然後拉最大記錄ID。然後我們再次在消息表上查詢,以僅從內部查詢結果集中獲取最新的記錄/消息。 –

+0

最簡單的解決方案恕我直言 – Nowdeen

2

該查詢返回的最後一個記錄:

SELECT m1.* 
    FROM messages m1 LEFT JOIN messages m2 
    ON (m1.Form_id = m2.Form_id AND m1.id < m2.id) 
    WHERE m2.id IS NULL; 
+0

老實說這個答案沒有得到重視。這是唯一對我有用的解決方案,因爲除了我的自動增量字段外,我正在使用不同的字段進行分組,而且我必須選擇最新的日期。 –

+0

這個答案幫助我使用Hibernate HQL。其他答案都不起作用,因爲Hibernate僅在WHERE和SELECT之後支持子查詢。由於這個答案根本不使用任何子查詢,所以它工作得很好。 – Alex

相關問題