MySQL有效率地取得每個分組的最後一筆記錄
在SQL中,提取每個分組的最新記錄可能比較棘手。常見場景是:表中有多筆記錄共用同一個主鍵,需要擷取每個主鍵的最新條目。本文提供了一種高效且最佳化的解決方案。
問題描述
考慮以下messages
表:
Id | Name | Other_Columns |
---|---|---|
1 | A | A_data_1 |
2 | A | A_data_2 |
3 | A | A_data_3 |
4 | B | B_data_1 |
5 | B | B_data_2 |
6 | C | C_data_1 |
使用SELECT * FROM messages GROUP BY Name
的基本分組查詢會產生以下結果:
Id | Name | Other_Columns |
---|---|---|
1 | A | A_data_1 |
4 | B | B_data_1 |
6 | C | C_data_1 |
然而,期望的輸出是每個分組的最新記錄:
Id | Name | Other_Columns |
---|---|---|
3 | A | A_data_3 |
5 | B | B_data_2 |
6 | C | C_data_1 |
解
使用視窗函數 (MySQL 8.0 及更高版本)
MySQL 8.0 引入了視窗函數,為查找每個分組的最後一筆記錄提供了一個優雅的解決方案。以下查詢利用ROW_NUMBER()
函數實現此目的:
<code class="language-sql">WITH ranked_messages AS ( SELECT m.*, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id DESC) AS rn FROM messages AS m ) SELECT * FROM ranked_messages WHERE rn = 1;</code>
使用LEFT JOIN (MySQL早期版本)
在 MySQL 8.0 之前,最有效的解決方案是使用 LEFT JOIN
:
<code class="language-sql">SELECT m1.* FROM messages m1 LEFT JOIN messages m2 ON (m1.name = m2.name AND m1.id < m2.id) WHERE m2.id IS NULL;</code>
效能與適用性
雖然兩種解決方案都很高效,但它們的效能可能會因資料的大小和分佈而異。對於大型且多樣化的資料集,通常建議使用視窗函數方法。
如果資料呈現特定模式(例如每個分組的記錄相對較少),則 LEFT JOIN
方法可能更有效率。
基準測試
在許多情況下,LEFT JOIN
方法已被證明優於分組技術。例如,在一個擁有數百萬行的大型資料庫中,LEFT JOIN
方法的執行時間不到一秒,而分組技術則需要一分鐘以上。
但是,始終建議在您的特定資料集上測試這兩種解決方案,以確定最佳方法。
以上是如何在MySQL中的每個組中有效找到最後一個記錄?的詳細內容。更多資訊請關注PHP中文網其他相關文章!