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

Oracle HAVING vs WHERE vs ON 深度解析:執行順序、效能差異與改寫技巧

     編輯:Oracle 資料庫基礎

三大條件子句執行順序

多表聯結查詢完整執行流程:

  1. ON:聯結條件,最先執行,過濾不符合聯結條件的列,減少中間結果集大小
  2. WHERE:聯結後過濾,在彙總計算前執行
  3. HAVING:分組彙總後過濾,最後執行

單表查詢:WHERE vs HAVING

避免使用 HAVING 的效能代價

  • HAVING 需要:排序 → 分組 → 彙總 → 過濾
  • WHERE 可在彙總前過濾,大幅減少參與彙總的資料量
  • 能用 WHERE 解決的,堅決不用 HAVING

子查詢減少表存取

-- 低效:多次存取 TAB_COLUMNS
SELECT tab_name FROM tables 
WHERE (tab_name, db_ver) = (SELECT tab_name, db_ver FROM tab_columns WHERE version = 604);

-- 高效:單次存取配合 EXISTS
SELECT tab_name FROM tables t
WHERE EXISTS (SELECT 1 FROM tab_columns c 
              WHERE c.tab_name = t.tab_name 
                AND c.db_ver = t.db_ver 
                AND c.version = 604);

內部函數提升 SQL 效率

  • 善用 DECODE、CASE、NVL、COALESCE 處理條件邏輯
  • 單次掃描完成複雜轉換,避免多次自聯結或子查詢
  • 12c+ 可用 APPROX_COUNT_DISTINCT 近似聚合加速

表別名最佳實踐

  • 多表聯結必須使用別名
  • 所有欄位引用加上別名前綴:e.empno、d.deptno
  • 減少解析時間、消除欄位歧義錯誤

EXISTS vs IN / NOT EXISTS vs NOT IN

場景WHEREHAVING建議
過濾條件不涉及彙總欄位可用 Rushmore 技術 (索引)無法用索引,需先彙總再過濾優先用 WHERE
過濾條件涉及彙總欄位 (SUM, COUNT 等)彙總前執行,欄位值未定 → 錯誤/無效彙總後執行,正確語意必須用 HAVING

改寫範例

-- 低效 NOT IN
SELECT * FROM emp WHERE deptno NOT IN (SELECT deptno FROM dept WHERE loc = 'MELB');

-- 高效 NOT EXISTS
SELECT * FROM emp e WHERE NOT EXISTS (
  SELECT 1 FROM dept d WHERE d.deptno = e.deptno AND d.loc = 'MELB'
);

-- 外部聯結替代 (舊版寫法)
SELECT e.* FROM emp e, dept d 
WHERE e.deptno = d.deptno(+) AND d.loc IS NULL;
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
對比IN / NOT INEXISTS / NOT EXISTS
子查詢執行通常先執行子查詢產生結果集相關子查詢,逐列驅動檢查
NULL 處理NOT IN 含 NULL 回傳空結果 (陷阱)正確處理 NULL 語意
效能大結果集時需排序合併滿足條件立即返回,適合大表驅動小表
全表掃描NOT IN 子查詢表常全表掃描可利用索引快速判斷