SQL如何合并多个查询结果?UNION与UNION ALL区别解析
SQL如何合并多个查询结果?UNION与UNION ALL区别解析
说到合并多个查询结果,UNION 和 UNION ALL 是绕不开的两个操作符。但选错一个,后果可能很严重:轻则查出意料之外的重复数据,重则直接拖垮整个查询的性能。尤其是在处理百万级数据表时,一个不经意的 UNION 可能比 UNION ALL 慢上好几倍,这可不是危言耸听。
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

简单来说,UNION 会去重但性能有损耗,而 UNION ALL 是纯拼接,速度更快,但前提是你得确保数据源本身没有重复。它们的使用有严格的规矩:列数、顺序、数据类型必须完全一致,否则数据库会直接报错。排序和去重的逻辑也需要开发者显式控制,不能依赖任何隐式行为。
列数、顺序和类型必须严格一致才能用 UNION / UNION ALL
想把两个查询的结果合并起来?首先得让它们“长得一样”。这意味着两个 SELECT 语句选出的列数必须相同,一个选3列,另一个选4列是行不通的。列的顺序也至关重要,第一个查询如果是 id, name, created_at,第二个写成 name, id, status 就会导致字段含义完全错乱——想象一下把用户名字段插入到ID列里会是什么结果。
数据类型的兼容性则是另一个常见陷阱。整数要对整数,字符串要对字符串。试图把 INT 和 VARCHAR 强行配对,可能会引发隐式转换失败,甚至导致数据被意外截断。
数据库可不会客气,一旦发现类型不匹配,报错信息会直接拍到你脸上,比如 Oracle 的 ORA-01790: expression must ha ve same datatype as corresponding expression,或者 PostgreSQL 的 ERROR: UNION types integer and text cannot be matched。
- 别依赖自动转换:永远不要指望数据库的隐式类型转换能帮你搞定一切。最稳妥的做法是使用
CAST(... AS ...)或COALESCE函数来显式对齐类型。 - 列名以第一个查询为准:合并后结果集的列名,完全由第一个
SELECT语句决定,后面子查询里起的别名统统无效。如果想改列名,必须在最外层再包装一个SELECT。 - 子查询条件需括号包裹:如果某个子查询需要附加
WHERE过滤条件或ORDER BY排序,务必用括号把它括起来。例如:(SELECT ... FROM t1 WHERE x > 0) UNION (SELECT ... FROM t2 ORDER BY y)。
UNION 自动去重,但代价是排序 + 去重计算
很多人以为 UNION 就是简单地把结果合并后再去掉重复行。其实不然,它的内部操作要复杂得多:通常是先将所有结果合并到一个临时工作区,然后按照所有列进行排序,最后再扫描相邻行来剔除重复项。这个过程意味着,即便你只希望保留重复记录中的某一条(比如最新的一条),UNION 也做不到——它只会随机保留一条,而且不保证是哪一条。
这种“排序+去重”的操作,对性能的影响是实实在在的。当每个子查询都返回十万行数据时,合并后的去重操作很可能触发磁盘上的临时文件排序,让原本毫秒级的查询响应,骤然降到秒级甚至更慢。
- 不要为了“整洁”而滥用:不要仅仅因为“看起来干净”就盲目使用
UNION。首先得问清楚:业务逻辑是否真的要求结果集必须唯一? - 确认数据源是否无重:如果数据源本身就不可能重复(例如从按日期分区的不同表里查询),那么直接使用
UNION ALL是更安全、更高效的选择。 - 排序必须显式控制:
UNION内部的排序行为是不可预测的,绝不能用它来替代ORDER BY。如果需要对最终结果排序,必须在外层显式地使用ORDER BY子句。
UNION ALL 是纯拼接,快但要自己管重复和顺序
UNION ALL 的逻辑就简单粗暴多了:它只是把第二个结果集“啪”地一下接到第一个结果集的后面,不做任何额外的排序、比较或去重。正因为如此,它的速度极快。
但这份“快”是有代价的:它会把所有数据原封不动地吐出来,包括那些本该被过滤掉的脏数据、测试数据,甚至是重复导入的记录。一个典型的误用场景是,用 UNION ALL 合并用户主表和历史备份表,结果导致同一个用户在结果集中间出现了两次,下游的统计计数直接翻倍,酿成数据事故。
- 确认逻辑隔离性:使用
UNION ALL前,必须确保各个子查询的数据在业务上是逻辑隔离的,比如来自不同的业务线、不同的日期分区,或者带有不同的状态标识。 - 排序同样需在外层:和
UNION一样,子查询内的ORDER BY通常会被忽略(除非配合LIMIT或窗口函数使用)。要对整个合并结果排序,必须在外层施加ORDER BY。 - 别指望它自动去重:虽然 MySQL 8.0+ 和 PostgreSQL 等数据库为
UNION ALL提供了一些高级优化(如WITH TIES),但它们都不会帮你自动去重。去重是你自己的责任。
什么时候该用 UNION,什么时候死守 UNION ALL
决策的核心其实只有一个问题:你能否接受结果中间出现重复行?
如果答案是“绝对不能”,并且无法从业务源头保证数据不重复(例如,需要合并正式员工表和外包人员表,两者的ID体系可能冲突,但姓名可能相同),那么别无选择,只能使用 UNION,并坦然接受随之而来的性能损耗。
反之,如果重复是可以忽略的(比如查询按天分区的日志表,每天的数据天然不重复),或者重复本身反而是有意义的信息(比如需要记录用户多次提交的操作流水),那么 UNION ALL 就是唯一合理且高效的选择。
- 避免画蛇添足:不要在
UNION外面再套一层DISTINCT,这不仅是语法上的冗余(UNION本身已包含去重语义),还可能让优化器困惑。 - 警惕嵌套过深:当
UNION嵌套层数过多(比如超过5层)时,数据库优化器的执行计划可能会退化。这时,考虑使用临时表或公共表表达式(CTE)预先进行数据聚合,往往是更好的方案。 - 生产环境务必压测:某些数据库(如 SQLite)对
UNION的排序策略在数据量小时表现良好,一旦上了生产环境,数据量激增,查询就可能突然卡住。因此,压力测试必不可少。
说到底,真正的难点往往不在于语法本身,而在于判断“这一行重复,到底算是个bug,还是个feature”。许多线上数据问题的根源,并不是SQL写错了,而是在按下“合并”按钮之前,没有想清楚一个根本问题:你究竟是想看到原始、完整的数据流,还是一份经过清洗的、去重后的视图?想明白了这一点,选择也就清晰了。
相关攻略
SQL如何合并多个查询结果?UNION与UNION ALL区别解析 说到合并多个查询结果,UNION 和 UNION ALL 是绕不开的两个操作符。但选错一个,后果可能很严重:轻则查出意料之外的重复数据,重则直接拖垮整个查询的性能。尤其是在处理百万级数据表时,一个不经意的 UNION 可能比 UNI
MySQL优化器如何处理UNION与UNION ALL 在数据库优化工作中,UNION和UNION ALL这对看似简单的集合操作符,背后隐藏的执行逻辑差异却常常被低估。很多性能问题,追根溯源,就出在对它们内部机制的理解偏差上。 UNION 和 UNION ALL 的执行计划差异 先明确一个核心区别:
热门专题
热门推荐
Titan Books正式公开《刺客信条:黑旗 记忆重置》官方艺术设定集 对于《刺客信条》系列的粉丝,尤其是那些对爱德华·肯威的海盗传奇念念不忘的玩家来说,最近有个值得关注的消息。育碧的长期合作伙伴Titan Books,正式揭晓了《刺客信条:黑旗 记忆重置》(Assassin s Creed: B
欧易OKX安卓版官方下载与安装全攻略 想在手机上安全、便捷地交易加密货币?欧易OKX交易平台的安卓版应用是个不错的选择。作为一款领先的数字资产交易工具,它为用户提供了全面的服务。下面这份详细的指南,将手把手带你完成从下载、安装到注册认证的全过程,帮你轻松上手。 一、欧易OKX应用下载指南 第一步,也
名越工作室YouTube频道“消失”又“复活”,新作《Gang of Dragon》前景仍不明朗 最近游戏圈里有个消息,让不少玩家心里咯噔了一下。彭博社此前报道,网易可能将停止资助由知名制作人名越稔洋(《如龙》《审判》系列之父)领衔的“名越工作室”。这一下,让团队正在开发的首款游戏《Gang of
各位玩家朋友们早上好! 今天是2026年4月25日星期六,欢迎收看今天的晨播报。今天的主要内容有:尼古拉斯·凯奇主演的《暗影蜘蛛侠》发布了全新海报,备受喜爱的猫猫冒险游戏《流浪》确认将登陆Switch2平台,而《最终幻想14》也正式公布了其下一个大型资料片。话不多说,一起来看看具体详情。 1、《蜘蛛
《星球大战:银河赛车手》发售日疑似泄露,豪华版内容抢先看 备受期待的《星球大战》系列赛车游戏新作,最近似乎不小心“说漏了嘴”。根据其Steam商店页面上一张预购奖励图的显示,《星球大战:银河赛车手》(Star Wars: Galactic Racer)的正式发售日期,很可能定在了2026年10月6日





