什么是 PostgreSQL UNION 操作符?
在数据库查询中,我们常常需要将多个查询结果合并成一个统一的列表。这时候,PostgreSQL 提供了一个非常实用的操作符——UNION。它就像一个“数据拼接器”,能把两个或多个 SELECT 查询的结果垂直合并在一起,形成一张新的结果表。
想象一下你有两个不同部门的员工名单,一个是销售部,一个是技术部。你想把这两个名单合起来,做一个全公司的员工汇总。如果分别查两个表,你会得到两份结果。但如果你用 PostgreSQL UNION 操作符,就能轻松地把它们“拼”成一份完整的名单,而且自动去除重复项。
这在实际开发中特别有用,比如你要整合来自不同业务模块的数据、合并历史与当前数据、或者做报表汇总等场景。它的核心优势在于:简洁、高效、自动去重。
不过要特别注意:使用 PostgreSQL UNION 操作符时,每个 SELECT 查询必须返回相同数量的列,且对应列的数据类型要兼容。这是它“拼接”的前提条件。
PostgreSQL UNION 操作符的基本语法
语法结构非常直观,就像写两个 SELECT 语句,中间用 UNION 连接:
SELECT 列1, 列2, ... FROM 表1
UNION
SELECT 列1, 列2, ... FROM 表2;
这里的关键点是:
- 两个 SELECT 语句的列数必须一致
- 对应列的数据类型必须可兼容(比如都是字符串、都是数字)
- 结果中会自动去除重复行
举个例子,我们有两个表:sales_staff 和 tech_staff,分别记录销售和技术人员的信息。
-- 查询销售部员工姓名和职位
SELECT name, position FROM sales_staff;
-- 查询技术部员工姓名和职位
SELECT name, position FROM tech_staff;
现在我们想把这两个结果合并成一张表,就可以这样写:
SELECT name, position FROM sales_staff
UNION
SELECT name, position FROM tech_staff;
✅ 注释:这个查询会返回所有员工的姓名和职位,如果某个人同时出现在两个部门(比如兼职),也会只显示一次,因为 UNION 默认去重。
UNION 与 UNION ALL 的区别
在使用 PostgreSQL UNION 操作符时,你可能会遇到另一个关键词:UNION ALL。它们的区别,就像“去重”和“全都要”的区别。
UNION:自动去重
当你使用 UNION,数据库会扫描最终结果,把完全相同的行去掉。这意味着如果你在两个查询中都查到了“张三,销售经理”,它只会保留一份。
SELECT '张三' AS name, '销售经理' AS position
UNION
SELECT '张三' AS name, '销售经理' AS position;
结果只有一行:
name | position
-------|----------
张三 | 销售经理
UNION ALL:保留所有行
而 UNION ALL 则不会去重,它直接把两个结果“堆”在一起。
SELECT '张三' AS name, '销售经理' AS position
UNION ALL
SELECT '张三' AS name, '销售经理' AS position;
结果有两行:
name | position
-------|----------
张三 | 销售经理
张三 | 销售经理
✅ 注释:如果你的数据量很大,或者你确定没有重复,使用 UNION ALL 会更快,因为它跳过了“去重”这一步计算。在性能敏感的场景下,这是一个非常实用的优化技巧。
实际案例:合并订单数据
假设我们有两个订单表:orders_2023 和 orders_2024,分别存储了去年和今年的订单信息。现在你想查看所有订单的总额和客户姓名。
-- 2023 年订单
SELECT customer_name, total_amount
FROM orders_2023
WHERE order_date >= '2023-01-01'
AND order_date < '2024-01-01';
-- 2024 年订单
SELECT customer_name, total_amount
FROM orders_2024
WHERE order_date >= '2024-01-01'
AND order_date < '2025-01-01';
现在用 PostgreSQL UNION 操作符把它们合并:
SELECT customer_name, total_amount
FROM orders_2023
WHERE order_date >= '2023-01-01'
AND order_date < '2024-01-01'
UNION
SELECT customer_name, total_amount
FROM orders_2024
WHERE order_date >= '2024-01-01'
AND order_date < '2025-01-01'
ORDER BY total_amount DESC;
✅ 注释:这个查询会返回两年所有订单的客户和金额,自动去重(比如同一个客户在两年都下了单,也不会重复出现),并按金额从高到低排序。非常适合生成年度销售报表。
数据类型兼容性与列数匹配
使用 PostgreSQL UNION 操作符时,最常出错的地方就是列数不一致或数据类型不兼容。
比如下面这个错误写法:
SELECT name FROM sales_staff
UNION
SELECT name, position FROM tech_staff;
这会报错,因为第一个查询返回 1 列,第二个返回 2 列。数据库无法“拼接”。
再比如:
SELECT name, age FROM sales_staff
UNION
SELECT name, salary FROM tech_staff;
虽然列数相同,但 age 是整数,salary 是数值类型(如 DECIMAL),虽然 PostgreSQL 通常能自动转换,但如果类型差异过大(比如一个是字符串,一个是日期),就会报错。
✅ 注释:建议在使用前,先用
SELECT * FROM 表 LIMIT 1查看列结构,确保字段数量和类型匹配。可以使用CAST函数手动转换类型,比如CAST(age AS TEXT)。
多个查询合并:链式使用 UNION
PostgreSQL UNION 操作符支持链式使用,也就是说你可以连接三个甚至更多查询。
比如我们有三个部门表:hr, finance, marketing,每个表都有 name 和 department 字段。
SELECT name, department FROM hr
UNION
SELECT name, department FROM finance
UNION
SELECT name, department FROM marketing;
✅ 注释:这个查询会把三个部门的员工信息合并成一张表,自动去重。如果某个员工跨部门任职,也只会出现一次。这种写法非常适合做全公司人员汇总。
你也可以结合 WHERE 条件和 ORDER BY:
SELECT name, department FROM hr
WHERE department = '人事部'
UNION
SELECT name, department FROM finance
WHERE department = '财务部'
UNION
SELECT name, department FROM marketing
WHERE department = '市场部'
ORDER BY name;
性能优化建议
虽然 PostgreSQL UNION 操作符功能强大,但在大数据量下仍需注意性能。
- 优先使用 UNION ALL:如果你确认数据无重复,就不要用 UNION,因为去重需要额外排序和比较,会增加 CPU 和内存开销。
- 合理使用索引:确保每个 SELECT 子句中使用的字段有索引,尤其是 WHERE 条件中的字段。
- 避免在 UNION 外层使用 ORDER BY:如果只是合并数据,不需要排序,就不要加 ORDER BY。如果必须排序,建议在每个 SELECT 内部先排序,再用 UNION ALL,最后整体排序。
常见错误与调试技巧
| 错误类型 | 原因 | 解决方案 |
|---|---|---|
| 列数不匹配 | 一个查询返回 2 列,另一个返回 3 列 | 检查 SELECT 字段数量,确保一致 |
| 数据类型不兼容 | 一个是 TEXT,一个是 DATE | 使用 CAST 转换类型,如 CAST(date_col AS TEXT) |
| 语法错误 | 缺少括号或换行混乱 | 使用清晰的换行和缩进,便于阅读 |
| 结果不按预期去重 | 你以为是唯一值,但实际有细微差异(如空格) | 检查数据是否真的相同,可用 TRIM() 去除空格 |
✅ 注释:调试时,先分别运行每个 SELECT,确认返回结果正常,再用 UNION 合并,能快速定位问题。
总结与使用建议
PostgreSQL UNION 操作符是一个强大而灵活的工具,尤其适合需要合并多个来源数据的场景。它不仅简化了查询逻辑,还自动处理重复项,让数据整合变得高效又可靠。
在日常开发中,你可以把它看作一个“数据拼接工具”:当你有两个结构相似但来源不同的数据表时,用它就能快速生成一张完整的汇总表。
记住几个关键点:
- 列数必须一致
- 对应列类型要兼容
- 需要去重就用 UNION,不需要就用 UNION ALL
- 多个查询可链式使用
- 避免在大数据量下滥用去重
掌握 PostgreSQL UNION 操作符,不仅能提升你的 SQL 写作能力,还能让你在处理数据整合任务时更加从容。无论是做报表、数据分析,还是系统间数据同步,它都是你不可或缺的利器。