一個查詢作為另一個查詢的條件。子查詢可嵌套在 SELECT、INSERT、UPDATE、DELETE 或另一子查詢中。
SELECT ... FROM 表1 WHERE 列1 > (子查詢)


子查詢回傳多行單欄或多欄(需用列建構器)。
-- 單欄 SELECT * FROM student WHERE student_id IN (SELECT student_id FROM absence); -- 多欄(列建構器) SELECT last_name, first_name, city, state FROM president WHERE (city, state) IN (SELECT city, state FROM president WHERE last_name = 'Roosevelt');
檢測子查詢結果集是否非空。EXISTS 為真/假,不回傳實際資料。
IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx')
-- 執行邏輯
子查詢參考外部查詢的欄位,外部查詢每行都會執行一次子查詢。
SELECT * FROM outer_table o WHERE EXISTS (SELECT 1 FROM inner_table i WHERE i.fk = o.pk AND i.status = 'active');
效能注意:相關子查詢在外部結果集上逐行執行,可能較慢。但寫得好(有索引支援)可勝過多連接+臨時表方案。
| 方法 | 用途 |
|---|---|
| UNION | 合併多個結果集的行 |
| 子查詢 | 將一個查詢嵌套在另一個中 |
| JOIN | 合併多個表的欄 |
-- 1. NOT IN(最慢:子查詢全表掃描+排序) SELECT a.hdr_key FROM hdr_tbl a WHERE a.hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl); -- 2. LEFT JOIN + IS NULL(較好) SELECT a.hdr_key FROM hdr_tbl a LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key WHERE b.hdr_key IS NULL; -- 3. NOT EXISTS(最快:無大量鎖定掃描) SELECT a.hdr_key FROM hdr_tbl a WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key);
-- 差:全表掃描計數 IF (SELECT COUNT(*) FROM table_name WHERE column_name = 'xxx') > 0 -- 好:找到第一筆即停止 IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx')
EXISTS/NOT EXISTS 替代 IN/NOT INWITH) 提升可讀度