PostgreSQL UNION 操作符(完整教程)

什么是 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_stafftech_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_2023orders_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,每个表都有 namedepartment 字段。

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 操作符功能强大,但在大数据量下仍需注意性能。

  1. 优先使用 UNION ALL:如果你确认数据无重复,就不要用 UNION,因为去重需要额外排序和比较,会增加 CPU 和内存开销。
  2. 合理使用索引:确保每个 SELECT 子句中使用的字段有索引,尤其是 WHERE 条件中的字段。
  3. 避免在 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 写作能力,还能让你在处理数据整合任务时更加从容。无论是做报表、数据分析,还是系统间数据同步,它都是你不可或缺的利器。