首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL UNION 與 ORDER BY 共用避坑指南:括號、子查詢與去重陷阱

     編輯:MySQL 資料庫相關知識

前言:UNION + ORDER BY 為何總報錯?

UNION 預設合併結果集並去重,ORDER BY 排序最終輸出。兩者結合時,MySQL 對語法位置有嚴格限制:無括號時只允許一個 ORDER BY 置於末尾;若需分別排序再合併,必須用子查詢包裹。本文以實例拆解三種正確寫法與常見誤區。

測試資料:表 t1

+----+----------+-------+
| id | username | score |
+----+----------+-------+
| 1  | lily     |  90   |
| 2  | lucy     |  85   |
| 3  | lily     |  80   |
| 4  | mike     |  95   |
| 5  | mary     |  88   |
+----+----------+-------+

測試表

錯誤示範:直接在兩邊加 ORDER BY

SELECT * FROM t1 WHERE username LIKE 'l%' ORDER BY score ASC
UNION
SELECT * FROM t1 WHERE username LIKE '%m%' ORDER BY score ASC;
-- ERROR 1221 (HY000): Incorrect usage of UNION and ORDER BY

原因:MySQL 解析器無法判斷兩個 ORDER BY 歸屬於哪個 SELECT,且 UNION 會重新排序去重,前置排序無意義。

正確寫法一:僅在末尾加 ORDER BY(全域排序)

SELECT * FROM t1 WHERE username LIKE 'l%'
UNION
SELECT * FROM t1 WHERE username LIKE '%m%' ORDER BY score ASC;

語義:先 UNION 去重合併,再對最終結果集按 score 升序。最常用、效能最好(可利用索引排序)。

正確寫法二:子查詢包裹各自排序(保留分組順序)

SELECT * FROM (
    SELECT * FROM t1 WHERE username LIKE 'l%' ORDER BY score ASC
) t3
UNION
SELECT * FROM (
    SELECT * FROM t1 WHERE username LIKE '%m%' ORDER BY score ASC
) t4;

關鍵: 每個 SELECT 必須包在括號內並給別名(t3, t4),內部 ORDER BY 才生效。但注意:UNION 仍會去重並重新排序,內部排序最終不一定保留(除非加 LIMIT)。

正確寫法三:UNION ALL + 子查詢(保留順序且不去重)

SELECT * FROM (
    SELECT * FROM t1 WHERE username LIKE 'l%' ORDER BY score ASC
) t3
UNION ALL
SELECT * FROM (
    SELECT * FROM t1 WHERE username LIKE '%m%' ORDER BY score ASC
) t4;

若業務需「第一組升序、第二組升序、兩組依序拼接」,只能用 UNION ALL 並確保無重複行,或在外層再包一層:

SELECT * FROM (
    SELECT 1 AS grp, * FROM t1 WHERE username LIKE 'l%' ORDER BY score ASC
    UNION ALL
    SELECT 2 AS grp, * FROM t1 WHERE username LIKE '%m%' ORDER BY score ASC
) t ORDER BY grp, score;

UNION vs UNION ALL 核心差異

特性UNIONUNION ALL
去重是(排序+唯一)否
效能較慢(臨時表+排序)快(直接流式輸出)
適用場景業務要求結果唯一已知無重複、或允許重複、效能優先

避坑清單

  1. 無括號時,ORDER BY **只能出現在最後一個 SELECT 之後**。
  2. 需分組排序 → 用 (SELECT ... ORDER BY ...) alias 子查詢包裹。
  3. 子查詢內的 ORDER BY 若無 LIMIT,MySQL 優化器可能忽略它(視版本而定),務必實測驗證。
  4. 大數據量優先 UNION ALL,應用層去重或加外層 DISTINCT。
  5. 所有 SELECT 欄位數、順序、類型必須一致,否則隱式轉換導致錯誤或錯誤結果。

掌握 UNION 與 ORDER BY 的語法邊界,能寫出既正確又高效的合併查詢,避免「明明加了排序卻不生效」的困擾。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved