首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 依部分欄位去重查詢:DISTINCT 與 GROUP BY 實戰技巧

     編輯:MySQL 資料庫相關知識

MySQL 依部分欄位去重查詢:DISTINCT 與 GROUP BY 實戰技巧

開發常遇到需求:依特定欄位組合去重,並保留符合條件的單筆記錄(如 ID 最大或最小)。DISTINCT 僅能處理「所有欄位完全相同」的情況,無法針對部分欄位去重。本文示範如何結合聚合函數與 GROUP BY 達標。

問題場景

假設資料表 mytable:

IDusernamepasswordTRDESC
1AabcdefQR
2AabcdefW34
3AbbbbbbAD
4Baaaaaaasdf

需求:username + password 組合去重,保留 ID 最大(或最小)的那一筆。

解法:子查詢 + GROUP BY + 聚合函數

保留 ID 最大的一筆

SELECT * 
FROM mytable 
WHERE ID IN (
    SELECT MAX(ID) 
    FROM mytable 
    GROUP BY username, password
);

保留 ID 最小的一筆

SELECT * 
FROM mytable 
WHERE ID IN (
    SELECT MIN(ID) 
    FROM mytable 
    GROUP BY username, password
);

原理解析

  1. GROUP BY username, password 將相同組合分成一組。
  2. MAX(ID) / MIN(ID) 在每組內取出極值 ID。
  3. 外層 WHERE ID IN (...) 篩選出完整欄位的該筆記錄。
關鍵限制:GROUP BY 後的 SELECT 清單只能包含分組欄位或聚合函數(MAX、MIN、COUNT、SUM 等),否則 MySQL(ONLY_FULL_GROUP_BY 模式)會報錯。

進階替代方案(MySQL 8.0+ 視窗函數)

使用 ROW_NUMBER() 更直觀、效能更佳:

WITH ranked AS (
    SELECT 
        *,
        ROW_NUMBER() OVER (PARTITION BY username, password ORDER BY ID DESC) AS rn
    FROM mytable
)
SELECT * FROM ranked WHERE rn = 1;
  • PARTITION BY username, password 依組合分組。
  • ORDER BY ID DESC 組內按 ID 遞減排序,第一筆即為最大 ID。
  • WHERE rn = 1 保留每組第一筆。

效能提示

  • 在 (username, password) 建立複合索引,加速分組與排序。
  • 資料量極大時,考慮分批處理或建立中間表。
  • 若需保留「最新修改時間」而非 ID,將 ORDER BY 改為對應時間欄位。

掌握「部分欄位去重 + 保留極值記錄」模式,可解決 90% 以上去重業務需求。MySQL 8.0 視窗函數寫法更優雅、可維護性更高,建議優先採用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved