首页/数据/SQL 速查/UNION 与 UNION ALL 合并结果集

UNION 与 UNION ALL 合并结果集

纵向拼接两个查询结果:UNION 去重、UNION ALL 保留全部行;能确定无重复时优先 UNION ALL,省去去重开销。

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

UNION 是什么

UNION 把两个查询结果纵向拼起来:UNION 会去重,UNION ALL 保留全部行。去重需要额外排序或哈希,代价明显,所以能确定两边没有重复时优先用 UNION ALL。参与合并的每个查询列数必须相同,列名以第一个查询为准,列类型要能互相兼容。数据类型不一致时数据库会做隐式转换,可能引入意外结果。整个 UNION 结果上要排序时,ORDER BY 只能写在最后一条查询之后,作用于合并后的整体。

基本信息

作用纵向合并多个查询的结果集
UNION合并并去重,代价高于 UNION ALL
UNION ALL保留全部行,不排序不去重
列要求列数相同,类型兼容,列名以第一个查询为准
排序ORDER BY 写在最后,作用于合并后的整体
平台差异MySQL 与 PostgreSQL 语法一致;PostgreSQL 另有 INTERSECT 与 EXCEPT

典型使用场景

  • 同类数据合并:把多张结构相同的归档表拼成一张结果
  • 多来源查询:不同渠道的数据汇总展示
  • 模拟全外连接:MySQL 不支持 FULL JOIN 时用左右连接加 UNION
  • 补齐维度:把缺失的分类行人为补进结果集
  • 分区表查询:把多个分区结果合并后统一排序
  • 拆分复杂条件:把 OR 条件拆成两条查询再 UNION ALL

示例

示例
-- 合并并按整体排序
SELECT id, name, 'active' AS src FROM users_active
UNION ALL
SELECT id, name, 'archived' AS src FROM users_archived
ORDER BY id DESC
LIMIT 100;

-- 需要去重时用 UNION(代价更高)
SELECT email FROM users_2023
UNION
SELECT email FROM users_2024;

-- 用 UNION 模拟全外连接
SELECT a.id FROM a LEFT JOIN b ON a.id = b.a_id
UNION
SELECT b.a_id FROM a RIGHT JOIN b ON a.id = b.a_id;

UNION 与 UNION ALL 对照

对比项UNIONUNION ALL
是否去重去重不去重
是否排序需要额外排序或哈希直接拼接
性能较慢更快
适用确实存在重复且要去掉确定无重复或重复可接受
结果行数小于等于两者之和等于两者之和
列名由第一个查询决定,后续查询的列名只作占位;给表达式列起一个统一的别名能让结果更清晰。
在单个查询里写 ORDER BY 或 LIMIT 需要加括号,MySQL 支持把子查询加括号后参与 UNION,写之前先确认目标版本支持。
UNION 去重会把两边本来就相同的行合并掉,统计总量时会比预期少;做数据量核对时先确认业务上是否希望去重。

使用要点

  • 默认用 UNION ALL,明确需要去重时才用 UNION
  • 两边列顺序与类型对齐,必要处显式转换类型
  • 表达式列统一别名,避免结果列名混乱
  • ORDER BY 与 LIMIT 只写在最后,作用于整体结果
  • 大批量合并时先把两边过滤好,减少参与排序的数据量
  • 用 EXPLAIN 确认去重带来的排序或临时表是否可接受

易错点

  • 用 UNION 代替 UNION ALL,白白承担去重的排序与临时表开销
  • 两边列顺序不一致,拼接后数据列错位且不容易发现
  • 把 ORDER BY 写在中间某条查询里,语法报错或排序范围与预期不符
  • 依赖 UNION 去重来清理数据,掩盖了上游数据重复的根本问题
  • 两边列类型不兼容触发隐式转换,数字被当成字符串比较

数据来源与参考

  • MySQL 8.0 Reference Manual · UNION
  • PostgreSQL Documentation · UNION
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌