UNION 和 UNION ALL
在 SQL 中,UNION
和 UNION ALL
用于合并多个 SELECT
语句的结果集。它们的主要区别在于是否处理重复行。以下是详细说明:
核心区别
特性 | UNION | UNION ALL |
---|---|---|
重复行处理 | 自动去除重复行 | 保留所有行(包括重复行) |
性能 | 较慢(需要去重操作) | 较快(直接合并结果) |
结果集排序 | 可能隐式排序(因去重需要) | 保留原始顺序 |
适用场景 | 需要唯一结果时 | 需要完整结果或已知无重复时 |
语法结构
SELECT column1, column2, ...
FROM table1
[WHERE conditions]UNION [ALL] -- 选择 UNION 或 UNION ALLSELECT column1, column2, ...
FROM table2
[WHERE conditions][ORDER BY column1, column2, ...]; -- 最终排序(只能出现在末尾)
关键注意事项
-
列数量和数据类型必须兼容
- 所有
SELECT
语句必须有相同数量的列。 - 对应列的数据类型必须兼容(如
INT
与BIGINT
可合并,但INT
与VARCHAR
可能报错)。
- 所有
-
列名和别名
- 最终结果集的列名取自第一个
SELECT
语句的列名或别名。 - 示例:
SELECT name AS employee_name FROM employees -- 结果列名为 employee_name UNION ALL SELECT product_name FROM products; -- 即使列名不同也不影响
- 最终结果集的列名取自第一个
-
排序(
ORDER BY
)ORDER BY
只能出现在最后一个SELECT
语句之后。- 对所有合并后的结果统一排序(不能在单个
SELECT
中使用)。 - 示例:
SELECT id, name FROM tableA UNION ALL SELECT id, name FROM tableB ORDER BY name; -- 正确:对整个结果排序
-
性能优化
- 优先用
UNION ALL
:除非明确需要去重,否则用UNION ALL
避免不必要的性能开销。 - 在
SELECT
中提前过滤数据:-- 优于先合并再过滤 SELECT * FROM table1 WHERE salary > 5000 UNION ALL SELECT * FROM table2 WHERE status = 'active'
- 优先用
-
去重逻辑
UNION
去重基于所有列的值组合。- 对
NULL
值的处理:所有NULL
被视为相等(即两行所有列均为NULL
会被去重)。
使用场景示例
场景 1:合并不重复数据(UNION
可以去重)
-- 获取所有唯一的城市名(客户和供应商)
SELECT city FROM customers
UNION
SELECT city FROM suppliers
ORDER BY city;
场景 2:合并所有数据(UNION ALL
)
-- 合并订单和退货记录(保留重复)
SELECT order_id, product_id FROM orders
UNION ALL
SELECT order_id, product_id FROM returns;
场景 3:处理不同列名(通过别名统一)
-- 合并员工和客户名称
SELECT first_name AS name FROM employees
UNION ALL
SELECT customer_name AS name FROM customers;
常见错误与解决方案
-
列数量不一致
-- 错误示例 SELECT id, name FROM tableA UNION SELECT id FROM tableB; -- 列数不同!-- 解决方案:补默认值 SELECT id, name FROM tableA UNION SELECT id, NULL AS name FROM tableB; -- 用 NULL 或空字符串填充
-
错误使用排序
-- 错误示例(ORDER BY 不在末尾) SELECT id FROM tableA ORDER BY id UNION SELECT id FROM tableB;-- 正确写法 SELECT id FROM tableA UNION SELECT id FROM tableB ORDER BY id;
-
误用
UNION
导致性能下降-- 错误:用 UNION 但实际不需要去重 SELECT * FROM small_table1 UNION -- 改为 UNION ALL 可提升性能 SELECT * FROM small_table2;
最佳实践总结
- 优先选择
UNION ALL
,除非明确需要去重。 - 确保所有
SELECT
语句的列数、数据类型兼容。 - 使用别名统一结果集的列名。
- 过滤数据尽量在单个
SELECT
中完成(而非合并后过滤)。 - 对最终结果排序时,
ORDER BY
只能放在语句末尾。
通过合理选择 UNION
或 UNION ALL
,可高效合并数据集并避免常见错误。