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

MySQL 去重查詢實戰:DISTINCT vs GROUP BY 的正確用法與陷阱

     編輯:MySQL 綜合教學

「查詢某欄位不重複的記錄,同時保留其他欄位」是常見需求,但 DISTINCT 與 GROUP BY 的行為差異常導致誤用。本文透過實例拆解兩者機制,給出正確去重寫法。

DISTINCT 的誤區

-- 表結構:id, name
-- 資料:(1,'a'), (2,'b'), (3,'c'), (4,'c'), (5,'b')

SELECT DISTINCT name FROM t;        -- ✅ 回傳 a,b,c
SELECT DISTINCT name, id FROM t;    -- ❌ 回傳全部 5 筆(name+id 組合唯一)
SELECT id, DISTINCT name FROM t;    -- ❌ 語法錯誤,DISTINCT 必須置於選項最前

核心規則:DISTINCT 作用於 整個選項列表的組合,而非單一欄位。無法「只對 name 去重、保留對應 id」。

GROUP BY 正確去重模式

MySQL 允許 GROUP BY 欄位未出現在選項中(非 ONLY_FULL_GROUP_BY 模式),且會自動取每組的第一筆記錄(非確定性,但常符合「取任一筆」需求)。

單表去重:取每個 name 的第一筆完整記錄

SELECT * FROM t GROUP BY name;

結果:(1,'a'), (2,'b'), (3,'c') —— 達到「name 不重複、保留其他欄位」目的。

多表 JOIN 去重:以主表主鍵分組

-- 原查詢:LEFT JOIN 導致 nid 重複
SELECT n.nid, n.title, ni.thumbpath
FROM term_node tn
JOIN node n ON n.nid = tn.nid
JOIN node_images ni ON ni.nid = n.nid
WHERE tn.tid IN (...)
ORDER BY n.nid DESC;

-- 修正:GROUP BY 主表主鍵
SELECT n.nid, n.title, ni.thumbpath
FROM term_node tn
JOIN node n ON n.nid = tn.nid
JOIN node_images ni ON ni.nid = n.nid
WHERE tn.tid IN (...)
GROUP BY n.nid
ORDER BY n.nid DESC;

DISTINCT vs GROUP BY 選擇指南

需求推薦寫法說明
只需統計不重複值的數量COUNT(DISTINCT col)標準 SQL,效能佳
需回傳去重欄位本身SELECT DISTINCT col語意清晰
需回傳去重欄位 + 其他欄位(單表)SELECT * FROM t GROUP BY colMySQL 擴展語法,簡潔
多表 JOIN 需以主表主鍵去重GROUP BY main_table.pk避免 JOIN 產生的重複行
嚴格 ANSI SQL 相容 / ONLY_FULL_GROUP_BY 模式子查詢 / 窗口函數 ROW_NUMBER()標準寫法,MySQL 8.0+ 原生支援

進階:MySQL 8.0+ 標準寫法(窗口函數)

SELECT * FROM (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id) AS rn
  FROM t
) x WHERE rn = 1;

此寫法語意明確、可控制保留哪一筆(如最新/最舊),為現代應用首選。

常見坑點提醒

  • GROUP BY 必須置於 ORDER BY、LIMIT 之前,否則語法錯誤。
  • 啟用 sql_mode=ONLY_FULL_GROUP_BY(MySQL 5.7+ 預設開啟)時,SELECT * GROUP BY col 會報錯,需改用窗口函數或聚合函數。
  • DISTINCT 可搭配聚合函數:COUNT(DISTINCT col),但無法搭配 WHERE 直接過濾。

總結

單表簡單去重用 GROUP BY 最快;多表 JOIN 去重以主表主鍵 GROUP BY;追求標準相容與可控保留邏輯,升級 MySQL 8.0 使用 ROW_NUMBER()。別再讓 DISTINCT 誤導你的查詢設計。

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