在SQL查询中,当需要将多个SELECT语句的结果集合并展示时,UNION和UNION ALL是最常用的两个操作符。二者都能实现结果集的拼接,但在去重逻辑和性能表现上存在明显差异,理解这些差异能帮助开发者写出更高效的SQL语句。

基础定义与核心差异
UNION和UNION ALL的核心作用都是合并多个SELECT语句的结果集,但处理逻辑完全不同:
- UNION:合并多个结果集后,会对最终结果执行去重操作,只保留唯一记录。
- UNION ALL:直接将所有结果集按顺序拼接,不会对结果做任何去重处理,重复记录会全部保留。
需要注意的是,使用这两个操作符时,所有SELECT语句必须满足列数相同、对应列的数据类型兼容的要求,否则会直接抛出语法错误。
执行逻辑对比
UNION的执行流程
UNION的执行过程可以分为三步:
- 依次执行各个SELECT语句,得到多个独立的结果集。
- 将所有结果集的数据整合到一起。
- 对整合后的全量数据执行去重操作,通常会使用排序或者哈希算法完成去重,最终返回唯一结果。
UNION ALL的执行流程
UNION ALL的执行过程非常简单:
- 依次执行各个SELECT语句,得到多个独立的结果集。
- 按照SELECT语句的书写顺序,直接将所有结果集拼接,不需要任何额外处理,直接返回结果。
性能差异分析
由于UNION需要额外的去重步骤,因此性能上和UNION ALL有明显差距,具体差异体现在以下方面:
| 对比维度 | UNION | UNION ALL |
|---|---|---|
| 额外操作 | 需要执行去重逻辑,通常涉及排序或哈希运算 | 无任何额外操作 |
| 资源消耗 | 消耗更多的CPU和内存资源,数据量越大消耗越高 | 资源消耗极低,仅需要拼接结果 |
| 执行速度 | 速度较慢,尤其是结果集数据量大的场景 | 速度极快,接近直接执行多个SELECT的总和 |
| 适用数据场景 | 结果集存在重复数据,且需要唯一结果 | 结果集无重复数据,或允许重复数据存在 |
代码示例演示
下面通过具体的SQL示例展示二者的使用差异,首先创建测试表并插入测试数据:
-- 创建测试表
CREATE TABLE test_user (
id INT,
user_name VARCHAR(50)
);
-- 插入测试数据
INSERT INTO test_user VALUES (1, '张三');
INSERT INTO test_user VALUES (2, '李四');
INSERT INTO test_user VALUES (1, '张三');
分别使用UNION和UNION ALL查询数据,观察结果差异:
-- 使用UNION查询,结果会去重 SELECT id, user_name FROM test_user WHERE id < 3 UNION SELECT id, user_name FROM test_user WHERE id > 0; -- 使用UNION ALL查询,结果保留重复 SELECT id, user_name FROM test_user WHERE id < 3 UNION ALL SELECT id, user_name FROM test_user WHERE id > 0;
第一个UNION查询的结果只会返回两条记录,分别是id为1和2的用户,重复的张三记录会被去除;第二个UNION ALL查询的结果会返回四条记录,包含两条重复的张三记录。
使用场景与选择建议
在实际开发中,可以按照以下原则选择使用UNION还是UNION ALL:
- 如果确认多个结果集之间不存在重复数据,或者业务允许重复数据存在,优先选择
UNION ALL,能大幅提升查询性能。 - 只有当业务明确要求结果集必须去重,且无法通过其他方式提前避免重复数据时,才选择
UNION。 - 如果结果集数据量非常大,即使需要去重,也可以先评估是否可以通过优化单个SELECT语句的逻辑,提前过滤重复数据,再使用UNION ALL合并,减少去重的性能消耗。
常见注意事项
- UNION的去重是对所有列的组合进行去重,而不是单独对某一列去重,如果需要单独对某一列去重,建议先使用DISTINCT处理单个结果集,再合并。
- 使用UNION时,排序操作只能放在最后一个SELECT语句之后,不能对每个单独的SELECT语句排序后合并。
- UNION和UNION ALL合并的结果集,列名以第一个SELECT语句的列名为准,后续SELECT语句的列名不会影响最终结果集的列名。