Oracle 提供三大集合運算子:UNION(聯集)、INTERSECT(交集)、MINUS(差集)。本文聚焦 INTERSECT 與 MINUS 實戰場景、語法規則、效能考量與替代寫法。
DISTINCT)。ORDER BY 僅能放在最後一個查詢之後,且需使用位置編號或別名。SELECT job FROM account
INTERSECT
SELECT job FROM research
INTERSECT
SELECT job FROM sales;
等價 JOIN 寫法(效能通常更好,可利用索引):
SELECT DISTINCT a.job
FROM account a
JOIN research r ON a.job = r.job
JOIN sales s ON a.job = s.job;
INTERSECT:欄位數/順序/型別相容、自動去重。A MINUS B ≠ B MINUS A(非交換律)。SELECT job FROM account
MINUS
SELECT job FROM sales;
等價 NOT EXISTS/LEFT JOIN 寫法:
-- NOT EXISTS(推薦,語意清晰)
SELECT DISTINCT a.job
FROM account a
WHERE NOT EXISTS (SELECT 1 FROM sales s WHERE s.job = a.job);
-- LEFT JOIN + IS NULL
SELECT DISTINCT a.job
FROM account a
LEFT JOIN sales s ON a.job = s.job
WHERE s.job IS NULL;
| 場景 | 推薦寫法 | 理由 |
|---|---|---|
| 大表交集/差集 | JOIN / NOT EXISTS / NOT IN | 可利用索引、哈希連接、並行查詢;集合運算子常需排序去重 |
| 小表/程式碼簡潔優先 | INTERSECT / MINUS | 語意直觀、SQL 簡短、維護容易 |
| 需保留重複列 | JOIN / NOT EXISTS | 集合運算子強制 DISTINCT |
| 跨資料庫 | 集合運算子 | DB Link 下語法簡潔,不需複雜分散式 JOIN |
-- INTERSECT 模擬:出現次數 = 表數
SELECT job
FROM (
SELECT job FROM account
UNION ALL
SELECT job FROM research
UNION ALL
SELECT job FROM sales
)
GROUP BY job
HAVING COUNT(*) = 3;
-- MINUS 模擬:僅出現在第一個來源
SELECT job
FROM (
SELECT job, 1 AS src FROM account
UNION ALL
SELECT job, 2 AS src FROM sales
)
GROUP BY job
HAVING COUNT(CASE WHEN src=1 THEN 1 END) > 0
AND COUNT(CASE WHEN src=2 THEN 1 END) = 0;
此法避免排序去重,配合並行查詢在億級資料上效能遠優於集合運算子。
SELECT a,b FROM t1 INTERSECT SELECT b,a FROM t2 → 錯誤比較。NUMBER vs VARCHAR2 存數字字串 → ORA-01790。ORDER BY 放在中間查詢 → ORA-00933。善用 INTERSECT/MINUS 解決「共同擁有」「僅擁有」類業務問題,大數據量時轉為 JOIN/NOT EXISTS 或 UNION ALL + GROUP BY 獲取最佳效能。