集合運算是 SQL 中處理多個查詢結果集的關鍵功能,屬於二元運算子,操作兩個結果集合。Oracle 提供四種標準集合運算子,皆要求參與運算的查詢:
查詢語句_1 { UNION | UNION ALL | INTERSECT | MINUS } 查詢語句_2 [...];
| 運算子 | 中文名稱 | 行為描述 | 去重複 | 效能特性 |
|---|---|---|---|---|
| UNION | 聯集 | 合併兩查詢結果,移除重複行 | 是 | 需排序比較,較慢 |
| UNION ALL | 聯集(含重複) | 合併兩查詢結果,保留所有行 | 否 | 無需排序,最快 |
| INTERSECT | 交集 | 僅回傳兩查詢皆有的行 | 是 | 需排序比較 |
| MINUS | 差集 | 回傳第一查詢有、第二查詢無的行 | 是 | 需排序比較 |
假設 DEPT 表有 4 筆資料(DEPTNO 10,20,30,40),第二查詢條件 WHERE deptno=10 僅回傳 1 筆。
SELECT * FROM dept UNION SELECT * FROM dept WHERE deptno = 10;
結果: 4 筆資料。DEPTNO=10 的行在兩查詢中皆出現,UNION 去重複後僅保留一筆。
SELECT * FROM dept UNION ALL SELECT * FROM dept WHERE deptno = 10;
結果: 5 筆資料。DEPTNO=10 的行出現兩次,UNION ALL 不移除重複。
SELECT * FROM dept INTERSECT SELECT * FROM dept WHERE deptno = 10;
結果: 1 筆資料。僅回傳兩查詢共有的 DEPTNO=10 行。
SELECT * FROM dept MINUS SELECT * FROM dept WHERE deptno = 10;
結果: 3 筆資料。回傳第一查詢有但第二查詢無的行(DEPTNO 20,30,40)。
Oracle 從左至右依序評估,INTERSECT 優先級高於 UNION/UNION ALL/MINUS。建議使用括號明確分組:
-- 先算交集,再聯集 SELECT * FROM dept WHERE deptno <= 20 UNION (SELECT * FROM dept WHERE deptno > 10 INTERSECT SELECT * FROM dept WHERE dname LIKE 'S%');
集合運算結果預設不保證順序。需在最後加上 ORDER BY(使用欄位位置或別名):
SELECT deptno, dname FROM dept WHERE deptno <= 20 UNION SELECT deptno, dname FROM dept WHERE deptno > 20 ORDER BY 1; -- 依第一欄位排序
EXISTS/NOT EXISTS、JOIN 在某些場景效能優於集合運算。TO_CHAR/TO_NUMBER。集合運算是集合論在 SQL 的直接映射,掌握 UNION/UNION ALL/INTERSECT/MINUS 的差異與適用場景,能寫出簡潔高效的資料整合查詢。實務上記住「能用 UNION ALL 就不用 UNION」,並善用括號控制運算順序,是資料工程師的基本功。