首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL DISTINCT 去重進階:單欄去重易、多欄保留非去重欄位難,GROUP BY 破解之道

     編輯:MySQL 綜合教學

問題場景

表結構:


id | name
1  | a
2  | b
3  | c
4  | c
5  | b

需求:查詢 name 不重複的所有資料,**並保留 id 欄位**。

DISTINCT 直接用法的侷限


SELECT DISTINCT name FROM t;           -- 僅返回 name,缺 id
SELECT DISTINCT name, id FROM t;       -- 對 (name,id) 組合去重,無效果
SELECT id, DISTINCT name FROM t;       -- 語法錯誤,DISTINCT 必須置首

GROUP BY 方案(MySQL 4.1+ 通用)


SELECT *, COUNT(DISTINCT name) FROM t GROUP BY name;

結果:


id | name | COUNT(DISTINCT name)
1  | a    | 1
2  | b    | 1
3  | c    | 1
原理:GROUP BY name 以 name 分組,每組取第一行(MySQL 允許非聚合欄位不在 GROUP BY 中),COUNT(DISTINCT name) 強制優化器識別去重邏輯,附帶計數欄位可忽略。

MySQL 4.0 舊版替代方案

若無 COUNT(DISTINCT) 支援(4.1 引入),可用任意聚合函數欺騙優化器:


SELECT *, COUNT(name) FROM t GROUP BY name;  -- 同樣有效

關鍵語法順序提醒


SELECT ... FROM ... WHERE ... GROUP BY ... ORDER BY ... LIMIT ...
鐵律:GROUP BY 必須置於 ORDER BY 和 LIMIT 之前,否則報錯。

現代最佳實踐(MySQL 5.7+/8.0)

  • 嚴格模式:ONLY_FULL_GROUP_BY 禁止非聚合欄位不在 GROUP BY 中
  • 規範寫法:SELECT MIN(id), name FROM t GROUP BY name 或 SELECT ANY_VALUE(id), name FROM t GROUP BY name
  • 窗口函數(8.0+):SELECT id, name FROM (SELECT id, name, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id) rn FROM t) x WHERE rn = 1

總結

MySQL 歷史版本寬鬆的 GROUP BY 語義曾是「去重保留其他欄位」的神奇技巧,現代嚴格模式下請改用明確聚合或窗口函數,語義清晰且跨資料庫可移植。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved