UNION 運算子 (SQL UNION Operator)
UNION 運算子用於將兩個 (或多個) SELECT 查詢的結果集垂直合併成一個結果集。它會自動移除重複的記錄,只返回不重複的值。
UNION 與 JOIN 的區別
- JOIN:橫向合併 (合併多個資料表的欄位,增加欄位數)
- UNION:垂直合併 (合併多個查詢的記錄,增加記錄數)
JOIN (橫向): UNION (垂直):
┌────┬────┐ ┌────────┐
│ A │ B │ │ A │
└────┴────┘ ├────────┤
│ B │
└────────┘
UNION 語法 (Syntax)
SELECT column_list FROM table1
UNION
SELECT column_list FROM table2;
使用 UNION 的條件:
- 每個 SELECT 語句必須有相同數量的欄位。
- 對應的欄位必須有相容的資料型別。
- 結果集的欄位名稱通常會依據第一個 SELECT 查詢的欄位名稱。
UNION 用法範例 (Example)
products_taiwan 資料表 (台灣地區銷售產品):
| P_Id | P_Name |
|---|---|
| 1 | LCD |
| 2 | CPU |
| 3 | RAM |
products_china 資料表 (中國大陸地區銷售產品):
| P_Id | P_Name |
|---|---|
| 1 | Keyboard |
| 2 | CPU |
| 3 | LCD |
範例: 查詢公司所有產品類別 (不重複)。
SELECT P_Name FROM products_taiwan
UNION
SELECT P_Name FROM products_china;
結果:
| P_Name |
|---|
| LCD |
| CPU |
| RAM |
| Keyboard |
注意:LCD 和 CPU 雖然在兩個表中都存在,但 UNION 自動去除了重複項,每個產品只出現一次。
UNION ALL (保留重複記錄)
如果需要保留所有記錄 (包括重複的),可以使用 UNION ALL:
SELECT P_Name FROM products_taiwan
UNION ALL
SELECT P_Name FROM products_china;
結果:
| P_Name |
|---|
| LCD |
| CPU |
| RAM |
| Keyboard |
| CPU |
| LCD |
UNION ALL 返回了全部 6 筆記錄,包括重複的 LCD 和 CPU。
UNION vs UNION ALL 效能比較
| 特性 | UNION | UNION ALL |
|---|---|---|
| 去除重複 | 是 | 否 |
| 執行速度 | 較慢 (需排序比較) | 較快 |
| 適用情境 | 需要唯一結果時 | 確定無重複或需保留重複時 |
💡 效能提示: 如果你確定兩個查詢結果不會有重複,或者不需要去除重複,使用
UNION ALL會有更好的效能,因為資料庫不需要額外進行排序和比較操作。
合併多個查詢
UNION 可以連接多個 SELECT 語句:
SELECT P_Name FROM products_taiwan
UNION
SELECT P_Name FROM products_china
UNION
SELECT P_Name FROM products_japan;
UNION 搭配 ORDER BY
ORDER BY 子句只能出現在整個 UNION 查詢的最後,用於對最終結果排序:
SELECT P_Name, 'Taiwan' AS Region FROM products_taiwan
UNION
SELECT P_Name, 'China' AS Region FROM products_china
ORDER BY P_Name; -- 對合併後的結果排序
⚠️ 注意:
ORDER BY不能出現在各個獨立的 SELECT 語句中 (除了使用子查詢)。
UNION 搭配 WHERE 條件
每個 SELECT 語句都可以有自己的 WHERE 條件:
SELECT Name, City FROM customers WHERE City = '台北市'
UNION
SELECT Name, City FROM suppliers WHERE City = '台北市';
這個查詢會返回所有位於台北市的客戶和供應商。
實際應用場景
1. 合併分散的資料表
當資料按時間或地區分散在多個表中時:
SELECT * FROM orders_2023
UNION ALL
SELECT * FROM orders_2024;
2. 建立報表資料
合併不同來源的資料,並加上識別欄位:
SELECT 'Customer' AS Type, Name, Phone FROM customers
UNION
SELECT 'Supplier' AS Type, Name, Phone FROM suppliers;
3. 模擬 FULL JOIN (在 MySQL 中)
MySQL 不支援 FULL JOIN,但可以用 UNION 模擬:
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
UNION
SELECT * FROM table1 RIGHT JOIN table2 ON table1.id = table2.id;
常見錯誤
欄位數量不一致
-- 錯誤:欄位數量不同
SELECT P_Id, P_Name FROM products_taiwan
UNION
SELECT P_Name FROM products_china; -- 只有一個欄位
資料型別不相容
-- 可能出錯:資料型別不相容
SELECT P_Id FROM products_taiwan -- INT
UNION
SELECT P_Name FROM products_china; -- VARCHAR
確保 UNION 的各個 SELECT 語句結構一致,是避免錯誤的關鍵。