萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

SQL 分組排序去重實戰:ROW_NUMBER() OVER (PARTITION BY ...) 保留每組最新一筆

場景

表 Eng24VIPCourseIntention 記錄用戶課程意向,同一 userid + classid 可能有多筆記錄(重複提交、歷史變更),需**保留每組最新一筆**(按 addtime DESC)。

標準解法:窗口函式 ROW_NUMBER()

SELECT *
FROM (
    SELECT 
        userid,
        classid,
        remark,
        ROW_NUMBER() OVER (
            PARTITION BY userid, classid
            ORDER BY addtime DESC
        ) AS row_rank
    FROM Eng24VIPCourseIntention
) AS t
WHERE row_rank = 1;

關鍵字解析

子句作用
PARTITION BY userid, classid分群鍵:同一用戶同一課程為一組
ORDER BY addtime DESC組內排序:最新在前
ROW_NUMBER()組內依序編號 1,2,3...
WHERE row_rank = 1只保留每組第一行(最新)

支援版本

  • MySQL 8.0+ 完整支援
  • PostgreSQL、SQL Server、Oracle、MariaDB 10.2+ 均支援
  • MySQL 5.7 需用變數模擬或升級

MySQL 5.7 替代方案(變數模擬)

SELECT userid, classid, remark
FROM (
    SELECT 
        userid, classid, remark,
        @rn := IF(@prev = CONCAT(userid, '#', classid), @rn + 1, 1) AS rn,
        @prev := CONCAT(userid, '#', classid)
    FROM Eng24VIPCourseIntention
    CROSS JOIN (SELECT @rn := 0, @prev := '') vars
    ORDER BY userid, classid, addtime DESC
) t
WHERE rn = 1;

效能提示

  • 窗口函式通常比自連接/子查詢去重快數量級。
  • 確保 PARTITION BY 欄位有索引,或建立 (userid, classid, addtime DESC) 覆蓋索引。
  • 大表可先 CREATE TEMPORARY TABLE 存中間結果再過濾。

總結

ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...) 是現代 SQL 去重保留最新/最舊/最高/最低的**標準寫法**,語意清晰、效能優異、跨資料庫通用。MySQL 8.0+ 請放心大膽用。

copyright © 萬盛學電腦網 all rights reserved