MySQL UNION 與 UNION ALL 完整指南:合併查詢結果的最佳實踐
UNION 與 UNION ALL 用於將多個 SELECT 查詢的結果集合併為單一結果集。理解其差異、排序規則與效能特性,能幫助你編寫高效的報表與統計查詢。
核心差異
| 特性 | UNION | UNION ALL |
| 去重 | 自動去除重複行 | 保留所有行(含重複) |
| 效能 | 需排序比較去重,較慢 | 直接合併,極快 |
| 適用場景 | 業務要求結果唯一 | 允許重複、追求極致效能、日誌分析 |
語法規則
SELECT 欄位列表 FROM 表1 WHERE 條件1
UNION [ALL]
SELECT 欄位列表 FROM 表2 WHERE 條件2
[ORDER BY 欄位] [LIMIT N];
關鍵限制:
- 欄位數量、順序、型別必須一致(隱含轉換可能導致錯誤)
ORDER BY 與 LIMIT 僅能置於最後,作用於整個合併結果
- 子查詢若需單獨排序/限制,必須用括號包裹:
(SELECT * FROM t1 ORDER BY id LIMIT 10)
UNION ALL
(SELECT * FROM t2 ORDER BY id LIMIT 10)
ORDER BY id LIMIT 20;
- 單獨在子查詢中使用
ORDER BY 會被優化器移除,無實際效果
實戰範例
-- 範例 1:合併兩張表的用戶名單(去重)
SELECT username FROM users_2023
UNION
SELECT username FROM users_2024;
-- 範例 2:保留重複(統計總登入次數)
SELECT user_id, login_time FROM login_log_jan
UNION ALL
SELECT user_id, login_time FROM login_log_feb
ORDER BY login_time DESC
LIMIT 100;
-- 範例 3:加上來源標識
SELECT '2023' AS year, username FROM users_2023
UNION ALL
SELECT '2024' AS year, username FROM users_2024;
效能優化建議
- **優先使用
UNION ALL**:除非業務強制去重,否則避免 UNION 的排序開銷
- **確保欄位型別一致**:避免隱含轉換導致索引失效
- **大結果集分頁**:配合
LIMIT offset, count 使用,但注意深分頁效能問題
- **利用索引**:各子查詢的
WHERE、ORDER BY 條件欄位應有適當索引
常見錯誤與解決
| 錯誤現象 | 原因 | 解決 |
| 「The used SELECT statements have a different number of columns」 | 欄位數量不一致 | 補齊欄位或使用 NULL 佔位 |
| 結果順序不符預期 | 未加 ORDER BY 或子查詢排序失效 | 在最外層加 ORDER BY |
| 去重後資料筆數異常 | UNION 按所有欄位比較去重 | 若僅需某欄位去重,先在子查詢 DISTINCT 再 UNION ALL |
- 上一篇文章: MySQL 核心知識圖譜:從基礎操作到進階特性全覽
- 下一篇文章: SQL 進階:單條語句統計登入日誌每用戶登入次數
Copyright ©
程式碼之家 All Rights Reserved