很多開發者在使用 UNION 合併結果集時,習慣在每個子查詢後加 ORDER BY,結果報錯:Incorrect usage of UNION and ORDER BY。其實 UNION 允許 ORDER BY,但有嚴格位置限制。
ORDER BY 作用於 整個合併後的結果集,而非最後一個子查詢。-- ❌ 錯誤:子查詢中使用 ORDER BY
SELECT * FROM t WHERE id > 10 ORDER BY id DESC
UNION
SELECT * FROM t WHERE id < 9 ORDER BY id DESC;
-- ✅ 正確:ORDER BY 放在最後,對全量結果排序
SELECT * FROM t WHERE id > 10
UNION
SELECT * FROM t WHERE id < 9
ORDER BY id DESC;
建立測試數據:
SELECT * FROM t WHERE id = 4
UNION
SELECT * FROM t WHERE id = 2
UNION
SELECT * FROM t WHERE id = 1
UNION
SELECT * FROM t WHERE id = 5
UNION
SELECT * FROM t WHERE id = 3;
若 UNION 只是簡單拼接,結果應為 4,2,1,5,3;實際返回卻是 1,2,3,4,5(主鍵順序)。證明 資料庫會統一優化整條語句,而非逐個執行子查詢再拼接。
直接在第一個子查詢加 LIMIT 2 只會限制該子查詢輸出,不影響整體結果。解決方案:
SELECT * FROM (
SELECT * FROM t WHERE id = 4
UNION
SELECT * FROM t WHERE id = 1
UNION
SELECT * FROM t WHERE id = 2
UNION
SELECT * FROM t WHERE id = 3
ORDER BY id ASC
) AS u LIMIT 2;
SET ROWCOUNT 2;
SELECT * FROM t WHERE id = 4
UNION
SELECT * FROM t WHERE id = 1
UNION
SELECT * FROM t WHERE id = 2
UNION
SELECT * FROM t WHERE id = 3
ORDER BY id ASC;
ROWCOUNT 作用於最終結果集,比 TOP 更規範。MySQL 請用方案一。
UNION + ORDER BY:ORDER BY 僅能放末尾,排序整體結果。UNION 再 LIMIT。UNION ALL。