MySQL 不支持 標準 SQL 的 INTERSECT / EXCEPT(8.0 仍不支持),需用 JOIN、IN/EXISTS、UNION 組合實現集合運算。
SELECT a.name
FROM student a
JOIN transcript t1 ON a.studid = t1.studid AND t1.crscode = 'CS305'
JOIN transcript t2 ON a.studid = t2.studid AND t2.crscode = 'CS315';
SELECT name FROM student
WHERE studid IN (SELECT studid FROM transcript WHERE crscode = 'CS305')
AND studid IN (SELECT studid FROM transcript WHERE crscode = 'CS315');
SELECT studid FROM (
SELECT studid FROM transcript WHERE crscode = 'CS305'
UNION ALL
SELECT studid FROM transcript WHERE crscode = 'CS315'
) t
GROUP BY studid
HAVING COUNT(*) = 2; -- 集合個數
SELECT * FROM table1
WHERE name NOT IN (SELECT name FROM table2 WHERE name IS NOT NULL);
SELECT * FROM table1 a
WHERE NOT EXISTS (SELECT 1 FROM table2 b WHERE b.name = a.name);
SELECT a.* FROM table1 a
LEFT JOIN table2 b ON a.name = b.name
WHERE b.name IS NULL;
-- 去重並集
SELECT name FROM table1
UNION
SELECT name FROM table2;
-- 全量並集(含重複,速度更快)
SELECT name FROM table1
UNION ALL
SELECT name FROM table2;
| 操作 | 推薦寫法 | 適用索引 | 備註 |
|---|---|---|---|
| 交集 | INNER JOIN | 被 JOIN 字段有索引 | 優化器可選擇 Hash Join (8.0.18+) |
| 差集 | NOT EXISTS / LEFT JOIN | 右表關聯字段有索引 | 避免 NOT IN 遇 NULL 導致全表掃描 |
| 並集 | UNION ALL + 外層 DISTINCT | 無特殊要求 | 業務允許重複時直接 UNION ALL |
-- 建立覆蓋索引
ALTER TABLE transcript ADD INDEX idx_crs_stud (crscode, studid);
-- 查詢將走 Index Only Scan,不回表
SELECT studid FROM transcript WHERE crscode = 'CS305'
INTERSECT -- 概念上
SELECT studid FROM transcript WHERE crscode = 'CS315';
MySQL 實際執行計劃會轉為 ref 訪問 + Using index,極快。
INNER JOIN,可讀性強、優化器成熟。NOT EXISTS 或 LEFT JOIN ... IS NULL,語義正確且性能穩定。UNION / UNION ALL。