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

MySQL DISTINCT 去重查詢實戰與效能優化深度探討

     編輯:MySQL 資料庫相關知識

從基礎語法到大表優化,系統講解 DISTINCT 使用陷阱、隱式排序開銷、避免最高層使用 DISTINCT 的設計原則,並以「哥譚市蝙蝠車購買者」案例演示如何用 EXISTS/IN 子查詢重構消除 DISTINCT。

基礎用法

SELECT DISTINCT * FROM table_name;
SELECT *, COUNT(DISTINCT col) FROM table GROUP BY col;  -- MySQL 版本需支援

優化原則:過濾條件先行、高選擇性優先

編寫查詢前對條件排序:真正高效的條件(能快速縮減資料量)應為主要驅動力。

反面教材:多表 JOIN + 頂層 DISTINCT

SELECT DISTINCT c.custname
FROM customers c
JOIN orders o ON o.custid = c.custid
JOIN orderdetail od ON od.ordid = o.ordid
JOIN articles a ON a.artid = od.artid
WHERE c.city = 'GOTHAM' AND a.artname = 'BATMOBILE' AND o.ordered >= ...;

弊端:
1. DISTINCT 掩蓋缺少連接條件導致的重複行。
2. 強制最終排序去重,開銷大。
3. 同名不同客戶會被誤去重(應返回 custid, custname)。

重構方案:EXISTS 關聯子查詢

SELECT c.custname FROM customers c
WHERE c.city = 'GOTHAM'
  AND EXISTS (
    SELECT 1 FROM orders o, orderdetail od, articles a
    WHERE a.artname = 'BATMOBILE'
      AND a.artid = od.artid AND od.ordid = o.ordid
      AND o.custid = c.custid AND o.ordered >= ...
  );
  • 外層無 DISTINCT,客戶唯一性由主鍵保證。
  • 子查詢為關聯子查詢,依賴外層 c.custid。

進階:非關聯子查詢 + IN

SELECT custname FROM customers
WHERE city = 'GOTHAM'
  AND custid IN (
    SELECT o.custid FROM orders o, orderdetail od, articles a
    WHERE a.artname = 'BATMOBILE' AND a.artid = od.artid
      AND od.ordid = o.ordid AND o.ordered >= ...
  );
  • 子查詢獨立執行一次,**隱式去重**(IN 不在乎重複值)。
  • 若 orderdetail.artid 有索引,先按商品名過濾再連接訂單更快。

內嵌視圖改寫(FROM 子查詢)

SELECT custname FROM customers
WHERE city = 'GOTHAM'
  AND custid IN (
    SELECT o.custid FROM orders o
    JOIN (SELECT DISTINCT od.ordid FROM orderdetail od, articles a
          WHERE a.artname = 'BATMOBILE' AND a.artid = od.artid) x
      ON x.ordid = o.ordid
    WHERE o.ordered >= ...
  );

改寫為 FROM 子查詢時,**必須顯式 DISTINCT** 去重,否則語義變化。

總結

  1. 正確結果只是第一步,**避免頂層 DISTINCT** 是寫好 SQL 的基本功。
  2. 優先用 EXISTS/IN 子查詢表達「存在性」,消除去重排序開銷。
  3. 選擇 IN 還是 EXISTS 取決於最強過濾條件位置(商品名 vs 日期)。
  4. 索引缺失會讓巧妙重構失效,EXPLAIN 驗證執行計劃不可少。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved