首页/数据/数据库速查/UNION 与 UNION ALL 集合运算
SQL 语法52 条

UNION 与 UNION ALL 集合运算

纵向拼接两个结果集:UNION 去重(有排序成本)、UNION ALL 保留全部(默认首选);列数类型必须兼容。

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

UNION 在做什么

UNION 把两个或多个 SELECT 的结果集纵向堆叠成一个结果集,列数和类型必须兼容,列名以第一个 SELECT 为准。UNION 对合并后的结果做去重,UNION ALL 保留全部行。去重需要额外的唯一化过程,可能借助临时表或排序,因此只要业务能接受重复行,UNION ALL 在性能上总是更优的选择。

基本信息

适用平台MySQL 5.7 / 8.0、MariaDB、PostgreSQL、Oracle
语法SELECT ... UNION [ALL] SELECT ... [ORDER BY ... LIMIT ...]
列约束各分支列数相同,类型可隐式转换
排序规则ORDER BY 与 LIMIT 作用于整个合并结果
默认去重UNION 去重,UNION ALL 不去重

典型使用场景

  • 多张结构相似的表合并成一份列表,例如订单表与退款表按同一口径输出
  • 同一张表按不同条件分段查再拼起来,避免复杂 OR 条件拖垮索引
  • 归档表加在线表的历史数据查询,用 UNION ALL 顺序拼接
  • 报表中把多个来源的明细合并后统一排序与分页
  • 用 UNION ALL 配合标记列,区分每条数据的来源

合并与排序写法

合并与排序写法
-- 结构一致时用 UNION ALL 保留全部行
SELECT id, 'order' AS src FROM orders WHERE created_at >= CURDATE()
UNION ALL
SELECT id, 'refund' AS src FROM refunds WHERE created_at >= CURDATE();
-- 需要去重时才用 UNION
SELECT phone FROM vip UNION SELECT phone FROM trial;
-- 分支要各自限行时必须加括号,否则 LIMIT 作用于整个结果
(SELECT id FROM t1 ORDER BY id LIMIT 10)
UNION ALL
(SELECT id FROM t2 ORDER BY id LIMIT 10)
ORDER BY id DESC LIMIT 20;

几种集合运算的区别

写法作用注意点
UNION ALL纵向堆叠并保留重复行性能最好,默认首选
UNION纵向堆叠并去重有唯一化成本,可能用临时表
JOIN横向扩展列与 UNION 维度不同,别混用
UNION 中的 ORDER BY作用于最终结果要限制单分支需给每个分支加括号
UNION 去重按整行所有列比较:只要两行在任一列上不同就不算重复,因此加了一个来源标记列后,看似相同的业务数据也不会被合并。
各分支列类型不一致时会按聚合规则隐式转换,转换为字符集或精度更高的类型,可能导致结果被截断或索引失效,输出前先显式 CAST。

易错点

  • 把 ORDER BY 与 LIMIT 写在某个分支后面却没加括号:排序与限行作用在整个 UNION 结果上,取到的是全局前 N 行而不是各分支前 N 行
  • 能用 UNION ALL 却写 UNION:多了一次去重的唯一化开销,数据量大时会明显变慢
  • 各分支列数不一致:直接报列数不匹配,脚本里拼接 SQL 时要显式对齐列
  • 靠隐式类型转换对齐列:会让被转换列上的索引失效,并可能造成数值精度丢失

数据来源与参考

  • MySQL 8.0 Reference Manual: UNION Clause

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌