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

SQL DISTINCT 與 GROUP BY 差異深度解析

     編輯:MySQL 綜合教學

SQL DISTINCT 與 GROUP BY 差異深度解析

兩者都能產生「不重複」結果集,但設計目的、適用場景、內部機制、擴展性截然不同。選錯不僅影響可讀性,更可能造成效能問題。

核心差異速查表

維度DISTINCTGROUP BY
設計目的移除結果集重複列將資料分組以便彙總計算
典型用法SELECT DISTINCT col FROM tSELECT col, COUNT(*) FROM t GROUP BY col
聚合函數不支援 (單純去重)核心搭配 (SUM, AVG, COUNT...)
多欄位去重DISTINCT col1, col2 (組合去重)GROUP BY col1, col2 (分組鍵)
結果排序不保證順序不保證順序 (需 ORDER BY)
NULL 處理視為一值,保留一筆 NULL形成獨立群組
HAVING 篩選不支援支援群組層級條件
執行計畫通常用 Hash Aggregate / Sort UniqueHash Aggregate / Sort Group

內部執行機制

  • DISTINCT:掃描資料 → 雜湊表/排序去重 → 輸出。只做去重,不準備彙總上下文。
  • GROUP BY:掃描資料 → 依分組鍵建立桶 → 維護彙總狀態 (計數、加總等) → 輸出。做更多工作:為聚合函數準備中間狀態。

因此:單純去重用 DISTINCT,語意更清晰、優化器路徑更短。

實測效能對比 (MySQL 8.0, 100 萬筆測試資料)

# 查詢 1: 去重
SELECT DISTINCT category FROM products;

# 查詢 2: 分組 (無聚合)
SELECT category FROM products GROUP BY category;

# 結果: 執行時間差異 < 5%,執行計畫相同 (Using index for group-by)
# 結論: 現代優化器對「無聚合的 GROUP BY」會優化為 DISTINCT 等價邏輯。

何時必須用 GROUP BY

✅ 需要彙總統計

SELECT department, COUNT(*) AS emp_cnt, AVG(salary) AS avg_sal
FROM employees
GROUP BY department;

✅ 需要 HAVING 篩選群組

SELECT customer_id, SUM(amount) AS total
FROM orders
GROUP BY customer_id
HAVING total > 10000;

✅ 多層級彙總 (ROLLUP/CUBE)

SELECT region, product, SUM(sales)
FROM sales_data
GROUP BY ROLLUP (region, product);

何時用 DISTINCT 更好

🎯 單純取得不重複值清單

# 取得所有有下單的客戶 ID
SELECT DISTINCT customer_id FROM orders;

# 取得不重複的標籤組合
SELECT DISTINCT tag1, tag2 FROM articles;

🎯 子查詢去重

SELECT * FROM users
WHERE id IN (SELECT DISTINCT user_id FROM logs WHERE action='login');

進階:DISTINCT ON (PostgreSQL 專有)

# 每類商品取最新一筆
SELECT DISTINCT ON (category) id, category, name, created_at
FROM products
ORDER BY category, created_at DESC;

MySQL 可用 ROW_NUMBER() OVER (PARTITION BY category ORDER BY created_at DESC) (8.0+) 達到同樣效果。

常見錯誤

  • SELECT DISTINCT col1, col2, col3 ... 後面跟大量欄位 → 實際上是在做「全列組合去重」,非單欄位去重。
  • SELECT col1, COUNT(*) FROM t GROUP BY col1 卻在 SELECT 加入未分組的 col2 → ONLY_FULL_GROUP_BY 模式報錯。
  • 誤以為 DISTINCT 比 GROUP BY 慢 → 現代優化器幾乎等價,關鍵在語意正確性。

決策流程圖

  1. 需要聚合函數 (COUNT/SUM/AVG...)? → GROUP BY
  2. 需要 HAVING 篩選群組? → GROUP BY
  3. 只需要「不重複的值/組合清單」? → DISTINCT
  4. 子查詢 IN/NOT IN 子句? → DISTINCT (語意更清晰)

掌握語意差異,寫出「對的 SQL」比寫「快的 SQL」更重要;語意正確,優化器自然幫你跑得快。

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