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 的條件:

  1. 每個 SELECT 語句必須有相同數量的欄位
  2. 對應的欄位必須有相容的資料型別
  3. 結果集的欄位名稱通常會依據第一個 SELECT 查詢的欄位名稱。

UNION 用法範例 (Example)

products_taiwan 資料表 (台灣地區銷售產品):

P_IdP_Name
1LCD
2CPU
3RAM

products_china 資料表 (中國大陸地區銷售產品):

P_IdP_Name
1Keyboard
2CPU
3LCD

範例: 查詢公司所有產品類別 (不重複)。

SELECT P_Name FROM products_taiwan
UNION
SELECT P_Name FROM products_china;

結果:

P_Name
LCD
CPU
RAM
Keyboard

注意:LCDCPU 雖然在兩個表中都存在,但 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 筆記錄,包括重複的 LCDCPU

UNION vs UNION ALL 效能比較

特性UNIONUNION 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 語句結構一致,是避免錯誤的關鍵。