0Pricing
Coding Interview Prep · 课时

UNION 与 UNION ALL

比较去重和性能方面的差异,并了解为什么通常应使用 UNION ALL

UNION 与 UNION ALL 是 CoddyKit 上的免费 Coding Interview Prep 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Coding Interview Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Coding Interview Prep 课程共包含 4 节课。

面试官为什么询问 UNION

集合运算会将一个结果集垂直堆叠到另一个结果集之上。UNION 和 UNION ALL 是面试官最先会采用的集合运算符,因为两者的区别只需一句话就能回答,却能体现您是否理解成本。

这个问题几乎总是这样表述的:“UNION 和 UNION ALL 有什么区别,应该使用哪一个?”优秀的回答会同时提到去重、排序和性能。

UNION 的作用

UNION 会将两个查询的行合并为一个结果集,然后删除重复行。只有每一列都相同的两行才算重复行。

为了删除重复行,执行引擎必须对所有合并后的行进行排序或哈希处理,这确实需要额外工作。从数学意义上说,UNION 返回的是一个集合:其中没有重复项。

SELECT city FROM customers
UNION
SELECT city FROM suppliers;

UNION ALL 的作用

UNION ALL 会拼接两个结果集并保留每一行,包括重复行。它不进行去重,因此不会为了去重而排序或进行哈希处理。

由于跳过了去重步骤,UNION ALL 几乎总是更快;当您确定行不会重叠,或确实需要重复行时,它就是正确的选择。

SELECT city FROM customers
UNION ALL
SELECT city FROM suppliers;

性能差异

面试中的核心结论是:UNION ALL 成本更低,因为它从不进行去重。UNION 必须将每个合并后的行与其他行进行比较,才能删除重复项。

  • UNION = UNION ALL + 一个隐式的 DISTINCT 步骤。
  • 对于大型结果集,这个 DISTINCT 步骤可能占据查询成本的主要部分。

如果不需要删除重复项,选择 UNION 就是在浪费 CPU 和内存。

包含重复项的示例

假设两个查询都可能返回行 'Paris'。使用 UNION 时,您会得到一个 Paris。使用 UNION ALL 时,您会得到两个 Paris。

面试官很喜欢让您预测行数。请始终先想象原始拼接结果,然后再问自己:这个运算符会删除重复项吗?

-- customers.city: Paris, Lyon
-- suppliers.city: Paris, Nice
-- UNION     -> Paris, Lyon, Nice   (3 rows)
-- UNION ALL -> Paris, Lyon, Paris, Nice (4 rows)

重复项根据所有列定义

一个常见陷阱是:只有每个选定列都相等时,两行才算重复。只要添加一列不同的值,这两行就不再重复,因此 UNION 会保留它们。

这就是为什么在相同的表上,使用 UNION 时,SELECT id, city 通常比 SELECT city 返回更多行。

SELECT id, city FROM customers
UNION
SELECT id, city FROM suppliers;
-- ids differ -> few or no duplicates removed

对合并结果排序

不能在各个分支上分别使用 ORDER BY;它作用于整个合并结果,并且必须在最后只出现一次。

面试官可能会问 ORDER BY 应该放在哪里。答案是:在最后一个查询之后使用一个 ORDER BY,并通过名称或位置引用输出列。

SELECT city FROM customers
UNION ALL
SELECT city FROM suppliers
ORDER BY city;

列名来自第一个查询

在最终的 ORDER BY 中引用列时,请使用第一个 SELECT 中的名称(或别名)。第二个查询的列名会被忽略,不会用于标注输出。

当各分支为列使用了不同名称时,这一点很重要。请为第一个分支设置别名,以控制输出表头。

SELECT city AS location FROM customers
UNION ALL
SELECT town FROM suppliers
ORDER BY location;

何时应选择 UNION

仅当确实可能存在重复行,并且您希望每个不重复的行只出现一次时,才使用 UNION。例如,合并两份联系人列表,其中同一人可能同时出现在两份列表中;或者从多个来源构建去重后的不重复值列表。

如果能够保证来源互不相交,UNION ALL 会得到相同结果,而且速度更快。

SELECT email FROM web_signups
UNION
SELECT email FROM store_signups;
-- one row per distinct email across both

何时应选择 UNION ALL

当不会出现重复行、重复行具有实际意义,或者您之后要进行聚合时,请使用 UNION ALL。一个经典模式是堆叠互不包含相同行的月度分区表。

面试提示:请说明 UNION ALL 是默认选择,只有确实需要去重时才升级为 UNION。

SELECT * FROM sales_2023
UNION ALL
SELECT * FROM sales_2024;

融会贯通

一份成熟的面试回答可以这样说:“UNION 会移除重复行,这会强制执行排序或哈希操作;UNION ALL 会保留所有内容,速度更快。两者都要求列数匹配且类型兼容,并且任何 ORDER BY 都只在末尾出现。我默认使用 UNION ALL,除非需要去重。”

这一句话同时体现了您对正确性和性能的认识。

快速检查

请检验您对 UNION 与 UNION ALL 区别的理解。

回顾

要点:

  • UNION = 合并并移除重复行(隐式 DISTINCT,额外开销)。
  • UNION ALL = 合并并保留全部内容,速度更快,是合理的默认选择。
  • 重复行要求所有列都匹配。
  • 单个 ORDER BY 放在最末尾,并使用第一个查询的列名。

默认使用 UNION ALL;只有真正需要去重时才升级为 UNION。

常见问题解答

「UNION 与 UNION ALL」课时是免费的吗?

是的 — 「UNION 与 UNION ALL」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Coding Interview Prep 课程的其余内容,请升级到 CoddyKit PRO。 Coding Interview Prep 课程共包含 4 节课。

「UNION 与 UNION ALL」这节课中我会学到什么?

比较去重和性能方面的差异,并了解为什么通常应使用 UNION ALL 你通过在浏览器中直接运行的动手代码来练习 Coding Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Coding Interview Prep 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Coding Interview Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「UNION 与 UNION ALL」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Coding Interview Prep 课中编写并运行代码吗?

能。每节 Coding Interview Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. UNION 与 UNION ALL
  2. 列数与类型兼容性
  3. 使用 INTERSECT 和 EXCEPT 进行比较
  4. 使用连接模拟集合运算
← 返回 Coding Interview Prep