給定結構完全相同的兩張表Student_1、Student_2,包含NAME、AGE、SCORE三列。需找出任一表中存在但另一表不存在、或字段值不同的記錄。即全外連接差集(Full Outer Join Difference)。
SELECT * FROM Student_1 S1
WHERE NOT EXISTS (
SELECT * FROM Student_2 S2
WHERE S1.name = S2.name AND S1.age = S2.age AND S1.score = S2.score
)
UNION ALL
SELECT * FROM Student_2 S2
WHERE NOT EXISTS (
SELECT * FROM Student_1 S1
WHERE S1.name = S2.name AND S1.age = S2.age AND S1.score = S2.score
);
優點:所有主流數據庫支持、正確處理NULL值、可利用索引。缺點:需掃描兩遍表、寫法冗長。
(SELECT * FROM Student_1 MINUS SELECT * FROM Student_2)
UNION ALL
(SELECT * FROM Student_2 MINUS SELECT * FROM Student_1);
注意:MySQL不支持MINUS/EXCEPT(8.0仍不支持),僅適用於Oracle、PostgreSQL、SQL Server等。語義清晰、優化器友好。
SELECT DISTINCT name, age, score FROM (
SELECT * FROM Student_1
UNION ALL
SELECT * FROM Student_2
) t
GROUP BY name, age, score
HAVING COUNT(*) = 1;
核心邏輯:UNION ALL合併保留重複→GROUP BY分組→HAVING COUNT(*)=1篩選只出現一次的行(即差異行)。
優勢:單次全表掃描、無子查詢、MySQL執行計劃友好、性能最優。前提:兩表結構完全一致,無NULL值干擾(NULL參與GROUP BY會單獨分組)。
| 方案 | 適用場景 | MySQL支持 | 性能 |
|---|---|---|---|
| NOT EXISTS | 通用、表較小、需精確匹配 | ✅ | 中 |
| MINUS/EXCEPT | Oracle/PG/SQL Server | ❌ | 高 |
| GROUP BY HAVING | MySQL大表、結構一致 | ✅ | 最高 |
MySQL環境下首選方案三;異構數據庫遷移或跨庫對比時,方案一通用性最強。