Skip to content

sql-union-vs-union-all

UNION 和 UNION ALL 是 SQL 中的集合运算符,用于将两个或多个 SELECT 语句的结果集合并为一个单一的结果集。当您在多个表中拥有类似结构的数据并希望将其视为一个整体时,这非常有用。

要使任何 UNION 操作成功,所涉及的 SELECT 语句必须是“联合兼容的”,这意味着它们必须满足两个严格条件:

  • 列数相同: 每个 SELECT 语句必须检索相同数量的列。
  • 数据类型兼容: 对应列的数据类型必须兼容(例如,您可以将 VARCHAR(50) 与 VARCHAR(100) 联合,或将 INT 与 DECIMAL 联合,但不能将 DATE 与 INT 联合)。

最终结果集中的列名取自第一个 SELECT 语句。

UNION 运算符合并结果集,然后执行一个额外的步骤:它扫描合并后的结果并删除任何重复的行。结果是所有查询中仅包含唯一行的集合。

SELECT column1, column2 FROM TableA
UNION
SELECT columnA, columnB FROM TableB;

假设一家公司将其员工存储在两个表中:FullTimeEmployees(全职员工)和 Contractors(承包商)。两个表都具有相似的结构。

-- 表:FullTimeEmployees
CREATE TABLE FullTimeEmployees (ID INT, Name VARCHAR(50));
INSERT INTO FullTimeEmployees VALUES
(1, 'Alice'),
(2, 'Bob');
-- 表:Contractors
CREATE TABLE Contractors (EmpID INT, FullName VARCHAR(50));
INSERT INTO Contractors VALUES
(3, 'Charlie'),
(1, 'Alice'); -- Alice 也做合同工

要获取公司所有人员的唯一列表,我们使用 UNION。请注意,‘Alice’ 的行出现在两个表中。

SELECT ID, Name FROM FullTimeEmployees
UNION
SELECT EmpID, FullName FROM Contractors;

UNION 删除了重复的 ‘Alice’ 行。

IDName
1Alice
2Bob
3Charlie

UNION ALL 运算符更简单、更快。它合并所有查询的结果集,但不执行任何重复项检查。它只是将第二个查询的行附加到第一个查询的行后面。

SELECT column1, column2 FROM TableA
UNION ALL
SELECT columnA, columnB FROM TableB;

使用相同的表,让我们看看 UNION ALL 会做什么。如果我们想计算工作合同的总数(包括重复项),这个查询会很有用。

SELECT ID, Name FROM FullTimeEmployees
UNION ALL
SELECT EmpID, FullName FROM Contractors;

UNION ALL 包含来自两个表的所有行,包括重复的 ‘Alice’。

IDName
1Alice
2Bob
3Charlie
1Alice

在实际应用中,最重要的区别在于性能。UNION ALL 显著快于 UNION。

这是因为 UNION 必须执行额外的工作来查找和消除重复行。这通常涉及对整个合并结果集进行排序或构建所有行的哈希表——这都是资源密集型操作,尤其是在大数据集上。

UNION ALL 不会执行这些操作。它只是简单地连接结果。这是一个轻量得多的操作。

最佳实践: 除非您明确需要删除重复行,否则请始终使用 UNION ALL。如果您知道合并查询的行已经不同,使用 UNION ALL 可以获得免费的性能提升。

特征UNIONUNION ALL
重复行删除重复项保留所有重复项
性能较慢(由于排序/哈希)较快(简单连接)
用例从多个来源获取唯一项列表。合并来自多个来源的所有记录,特别是用于 COUNT 等聚合操作或当您知道不可能有重复项时。