Skip to content

PostgreSQL - UNION 运算符

在 PostgreSQL 中,UNION 操作符用于将两个或多个 SELECT 语句的结果集合并为一个结果集。它会从合并结果中移除重复行,确保每行都是唯一的。

要使用 UNION,所有 SELECT 语句必须具有相同数量的列,并且对应的列必须具有兼容的数据类型。列名由第一个 SELECT 语句决定。

SELECT column1, column2, ... FROM table1 [WHERE condition1]
UNION
SELECT column1, column2, ... FROM table2 [WHERE condition2];

想象一家公司将工程部门和销售部门的员工存储在不同的表中。我们希望创建一个统一的联系人列表。

首先,让我们创建并填充示例表:

-- 工程部门员工表
CREATE TABLE engineering_team (
id SERIAL PRIMARY KEY,
full_name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE
);
-- 销售部门员工表
CREATE TABLE sales_team (
id SERIAL PRIMARY KEY,
full_name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE
);
-- 插入数据
INSERT INTO engineering_team (full_name, email) VALUES
('Alice Johnson', 'alice.j@example.com'),
('Bob Williams', 'bob.w@example.com'),
('Charlie Brown', 'charlie.b@example.com');
INSERT INTO sales_team (full_name, email) VALUES
('David Smith', 'david.s@example.com'),
('Charlie Brown', 'charlie.b@example.com'),
('Eve Davis', 'eve.d@example.com');

请注意,‘Charlie Brown’ 在两个表中都存在。现在,让我们使用 UNION 获取所有员工的唯一列表:

SELECT full_name, email FROM engineering_team
UNION
SELECT full_name, email FROM sales_team;

此查询生成以下结果,其中 ‘Charlie Brown’ 只出现一次:

全名电子邮件
Alice Johnsonalice.j@example.com
Bob Williamsbob.w@example.com
Charlie Browncharlie.b@example.com
David Smithdavid.s@example.com
Eve Daviseve.d@example.com

UNION ALL 操作符也合并结果集,但它包含所有行,包括重复行。它比 UNION 更快,因为它不需要执行识别和移除重复行的额外步骤。

SELECT column1, column2, ... FROM table1 [WHERE condition1]
UNION ALL
SELECT column1, column2, ... FROM table2 [WHERE condition2];

使用相同的表,让我们看看 UNION ALL 的结果:

SELECT full_name, email FROM engineering_team
UNION ALL
SELECT full_name, email FROM sales_team;

此查询将 ‘Charlie Brown’ 包含两次:

全名电子邮件
Alice Johnsonalice.j@example.com
Bob Williamsbob.w@example.com
Charlie Browncharlie.b@example.com
David Smithdavid.s@example.com
Charlie Browncharlie.b@example.com
Eve Daviseve.d@example.com

使用 ORDER BY 对合并结果进行排序

Section titled “使用 ORDER BY 对合并结果进行排序”

要对 UNION 或 UNION ALL 查询的最终结果集进行排序,请将 ORDER BY 子句放在整个语句的末尾。它将应用于合并后的结果。

SELECT full_name, email FROM engineering_team
UNION
SELECT full_name, email FROM sales_team
ORDER BY full_name ASC;

这将生成一个唯一的、已排序的员工列表:

全名电子邮件
Alice Johnsonalice.j@example.com
Bob Williamsbob.w@example.com
Charlie Browncharlie.b@example.com
David Smithdavid.s@example.com
Eve Daviseve.d@example.com
  • 性能: 如果你确定没有重复项或重复项可以接受,请使用 UNION ALL 而非 UNION。UNION ALL 避免了排序和移除重复项的开销,使其显著更快。
  • 列不匹配: 常见的错误是 SELECT 语句中的列数量不同或数据类型不兼容。请确保它们完全匹配。
  • 数据类型: 如果对应的列具有不同但兼容的数据类型(例如,INT 和 BIGINT),PostgreSQL 会将它们转换为一个共同的超类型(例如,BIGINT)。
  • 列别名: 最好在第一个 SELECT 语句中使用列别名以提高清晰度,因为这些名称将用于最终结果集。