當需要「某欄位值在一組值中」時,常見寫法有二:
-- 寫法 1:IN 子查詢
WHERE column IN (SELECT col FROM table2 WHERE ...);
-- 寫法 2:EXISTS 相關子查詢
WHERE EXISTS (SELECT 'X' FROM table2 WHERE table2.col = table1.column AND ...);
NOT IN 若子查詢回傳 NULL 會導致整個判斷為 UNKNOWN(無資料回傳),且同樣需建立臨時表。NOT EXISTS 無此問題,效能也更穩定,強烈建議統一改用 NOT EXISTS。
-- 原本 IN 寫法
SELECT * FROM Orders o
WHERE o.CustomerID IN (SELECT CustomerID FROM Customers WHERE Country = 'USA');
-- 改用 EXISTS
SELECT * FROM Orders o
WHERE EXISTS (
SELECT 1 FROM Customers c
WHERE c.CustomerID = o.CustomerID
AND c.Country = 'USA'
);
| 情境 | 建議 |
|---|---|
| 子查詢結果集極小(< 100 列)且無 NULL | IN 可讀性較好,效能差異微乎其微 |
| 子查詢結果集大、或含 NULL、或需相關欄位比對 | EXISTS / NOT EXISTS |
單純常值清單(如 IN (1,2,3)) | 直接用 IN,最簡潔 |
掌握這兩者差異,能在撰寫高效能 SQL 時做出正確選擇。