首页/数据/SQL 速查/集合运算中的 ORDER BY 与 LIMIT

集合运算中的 ORDER BY 与 LIMIT

ORDER BY/LIMIT 写在最后时作用于整个合并结果;要给单个分支排序或限行,必须用括号包住该分支。

SQL 速查数据更新于 2026-10-13

集合运算里的排序与限行

把多个查询结果拼在一起时,排序与限行的作用范围由位置决定:写在整条语句最后,作用于合并后的完整结果;写在某个分支内部,只作用于该分支自己。要让单个分支排序或限行,必须用括号把这个分支包起来,否则语句的解析结果与预期完全不同。这个细节在处理「每个来源取前若干条再合并」的需求时特别关键。

基本信息

适用平台MySQL 8.0 / PostgreSQL 12 及以上
整体排序写在最后,作用于合并后的结果
分支限行分支用括号包裹,各自写排序与限行
列结构要求各分支的列数一致、顺序对应、类型兼容
去重差异保留全部用不去重形式,否则会额外做一次去重

典型使用场景

  • 多个来源各取最新若干条再合并展示(典型的信息流场景)
  • 分表数据合并统计:先合并再聚合
  • 多条件筛选结果拼成一个列表,最后统一排序分页
  • 跨库或跨表去重合并:需要显式指定去重形式
  • 排查结果行数异常:确认是分支限行没生效还是整体排序缺失

作用范围示例

作用范围示例
-- 分支各自取最近的 5 条,最后对合并结果整体排序
(SELECT id, name FROM t1 ORDER BY id DESC LIMIT 5)
UNION ALL
(SELECT id, name FROM t2 ORDER BY id DESC LIMIT 5)
ORDER BY id;                 -- 这一句作用于合并后的整体

-- 分表合并后再聚合:聚合放在最外层
SELECT city, SUM(amount) AS total, COUNT(*) AS cnt
FROM (
    SELECT city, amount FROM orders_2023
    UNION ALL
    SELECT city, amount FROM orders_2024
) t
GROUP BY city
ORDER BY total DESC;

-- 分支只写限行不写排序,取到哪几行不确定
-- SELECT id FROM t1 LIMIT 5   ← 不要这样用,先加排序

位置与作用范围

写法位置作用范围注意事项
语句最后合并后的整体结果最外层排序决定最终顺序
分支内部(有括号)该分支自己的结果必须用括号包住分支
分支内部(无括号)解析结果与预期不同常见误解来源,务必加括号
分支只写限行取行不确定不写排序时结果不可预期
去重形式合并时是否去重分支之间有重复数据时影响行数
最外层排序会覆盖分支内部排序产生的顺序:分支排序只决定该分支贡献了哪几行,最终呈现顺序完全由最外层决定。想保留「按来源分组」的展示效果,需要在结果里额外带一个来源标记列并据此排序。
分支数量多时,各分支都写排序加限行会让优化器难以统一优化。数据量大时考虑改写成窗口函数一次性取数,通常比多个分支各自扫描更经济。

易错点

  • 把排序写在第一个分支里却期望整体有序:分支排序只对自身生效,需放在最后
  • 分支限行不加括号,解析结果与预期不符,取到的行完全不是想要的那一批
  • 分支只写限行不写排序,取到哪几行由执行顺序决定,结果不稳定
  • 各分支列类型不一致(整数与长整数混用)触发隐式转换,统一显式类型
  • 对分表合并结果先聚合再合并,口径算错:合并必须发生在聚合之前

数据来源与参考

  • MySQL 8.0 Reference Manual · UNION · ORDER BY and LIMIT
  • PostgreSQL Documentation · Combining Queries
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌