表結構:
id | name
1 | a
2 | b
3 | c
4 | c
5 | b
需求:查詢 name 不重複的所有資料,**並保留 id 欄位**。
SELECT DISTINCT name FROM t; -- 僅返回 name,缺 id
SELECT DISTINCT name, id FROM t; -- 對 (name,id) 組合去重,無效果
SELECT id, DISTINCT name FROM t; -- 語法錯誤,DISTINCT 必須置首
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)強制優化器識別去重邏輯,附帶計數欄位可忽略。
若無 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之前,否則報錯。
ONLY_FULL_GROUP_BY 禁止非聚合欄位不在 GROUP BY 中SELECT MIN(id), name FROM t GROUP BY name 或 SELECT ANY_VALUE(id), name FROM t GROUP BY nameSELECT id, name FROM (SELECT id, name, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id) rn FROM t) x WHERE rn = 1MySQL 歷史版本寬鬆的 GROUP BY 語義曾是「去重保留其他欄位」的神奇技巧,現代嚴格模式下請改用明確聚合或窗口函數,語義清晰且跨資料庫可移植。