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

MySQL UNION 全解析:語法、排序陷阱與分頁實戰

     編輯:MySQL 資料庫相關知識

UNION 是合併多個 SELECT 結果集的利器,但其排序規則、去重機制與分頁用法常讓開發者踩坑。本文系統梳理 UNION 核心語法、排序原理、ThinkPHP 等框架下的複雜實現,並給出論壇「置頂+最新」混合分頁的最佳實踐。

一、UNION 核心語法與特性

SELECT ...
UNION [ALL | DISTINCT]
SELECT ...
[UNION [ALL | DISTINCT] SELECT ...]
  • 去重預設:不加 ALL 時等同 UNION DISTINCT,會對全量結果排序去重,性能開銷大。
  • 列對齊要求:各 SELECT 列數、順序、類型必須一致;結果集列名以第一個 SELECT 為準。
  • 限制條款:僅最後一個 SELECT 可用 INTO OUTFILE;HIGH_PRIORITY 僅對第一個生效,其餘報錯。

二、排序與 LIMIT 的正確姿勢

1. 全局排序:包裹子查詢 + 外層 ORDER BY

(SELECT a FROM tbl WHERE a=10 AND b=1)
UNION
(SELECT a FROM tbl WHERE a=11 AND b=2)
ORDER BY a LIMIT 10;

⚠️ 關鍵規則:ORDER BY 不能使用 表名.列名,必須用第一個 SELECT 的列別名或列位置(推薦別名)。

-- 正確:使用別名
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b;

-- 錯誤:使用原列名
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a; -- Unknown column 'a'

2. 子查詢獨立排序:括號內加 ORDER BY/LIMIT

(SELECT a FROM tbl WHERE a=10 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM tbl WHERE a=11 ORDER BY a LIMIT 10);

此時各子查詢先各自排序截取,再合併(不再全局排序)。

三、實戰場景:博客「置頂帖優先 + 普通帖分頁」

需求:置頂帖(top=1)按時間倒序,普通帖(top=0)按時間倒序,合併後統一分頁。

(SELECT * FROM `blog` WHERE top=1 ORDER BY created DESC)
UNION
(SELECT * FROM `blog` WHERE top=0 ORDER BY created DESC)
LIMIT 2, 3;  -- 跳過前 2 條,取 3 條

注意:兩端 SELECT * 列數須一致;若結構不同,用 NULL 佔位對齊。

四、UNION ALL vs UNION:性能抉擇

特性UNIONUNION ALL
去重是(全量排序去重)否(直接拼接)
速度慢(臨時表+文件排序)快(流式輸出)
適用場景結果集可能重複,且需去重確定無重複,或業務允許重複

典型案例:當前表 UNION 歷史表 確無重複主鍵 → 必用 UNION ALL。

五、雙向排序難題:論壇「前 3 點擊最高 + 其餘按時間」

單條 SQL 實現:

SELECT *, 1 AS ord FROM `women`
WHERE status=2 AND (title LIKE '%2014%' OR title LIKE '%秋冬%')
UNION
(SELECT *, 2 AS ord FROM `women`
 WHERE status=2 AND (keywords LIKE '%2014%' OR keywords LIKE '%秋冬%'))
ORDER BY ord, id DESC LIMIT 0, 15;

原理:用常量列 ord 標記優先級,外層按 ord, id DESC 排序,實現分組內各自排序 + 分組間優先級排序。

六、ThinkPHP 等框架中的複雜 UNION 實現

框架 union() 方法通常僅支持簡單合併。複雜場景(如子查詢排序、聯合後再排序)建議:

  1. 使用 query() 或 execute() 直接寫原生 SQL。
  2. 或拆分為多次查詢,應用層合併排序(數據量小時可行)。

總結速查表

  • 需去重用 UNION,確無重複用 UNION ALL(快 3-5 倍)。
  • 全局排序:子查詢加括號,外層 ORDER BY 別名。
  • 分組內排序:子查詢括號內寫 ORDER BY LIMIT。
  • 列名不一致時用 NULL AS col 對齊。
  • 複雜邏輯別硬用框架封裝,原生 SQL 更可控。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved