Skip to content

MySQL - UNION vs JOIN

在关系型数据库中,数据通常分散在多个表中。为了获取完整的信息,您需要组合这些数据。MySQL 提供了两个主要工具来实现这一点:UNION 和 JOIN。尽管两者都用于组合数据,但它们以根本不同的方式和出于不同的目的进行。

根本区别:拓宽数据 vs. 增长数据

Section titled “根本区别:拓宽数据 vs. 增长数据”

理解它们之间区别的最简单方法是类比:

  • JOIN 从其他表添加列。 它通过在其他表中查找相关数据并将其添加为新列,使您的结果集变得更宽。可以想象成在第二个电子表格中查找信息,并将其添加到第一个电子表格中匹配行的旁边。
  • UNION 从其他查询添加行。 它通过将一个查询的结果堆叠在另一个查询之上,使您的结果集变得更长。可以想象成从第二个电子表格中复制行,并将其粘贴到第一个电子表格的底部。

UNION 运算符组合两个或多个 SELECT 语句的结果集。它有两条严格的规则:

  • 在 UNION 中的每个 SELECT 语句必须具有相同数量的列。
  • 列的数据类型也必须相似,并且顺序相同。

默认情况下,UNION 会从最终结果集中移除重复行。如果您想包含所有行,包括重复项,请使用 UNION ALL,它也更快,因为它不需要检查重复项。

示例:组合活跃用户和已归档用户

Section titled “示例:组合活跃用户和已归档用户”

假设您有两个结构相似的表:active_users(活跃用户)和 archived_users(已归档用户)。要获取所有用户电子邮件的单一列表,您将使用 UNION。

-- 表:active_users
-- +----+------------------+
-- | id | email |
-- +----+------------------+
-- | 1 | alice@example.com|
-- | 2 | bob@example.com |
-- +----+------------------+
-- 表:archived_users
-- +---------+-------------------+
-- | user_id | user_email |
-- +---------+-------------------+
-- | 101 | charlie@example.com |
-- | 2 | bob@example.com |
-- +---------+-------------------+
-- UNION 查询:
SELECT email FROM active_users
UNION
SELECT user_email FROM archived_users;

SELECT 列表中的列名可以不同(email vs. user_email),但它们的数量(一个)和数据类型(VARCHAR)必须兼容。最终结果将只有一列,并且重复的 ‘bob@example.com’ 将被移除。

email
alice@example.com
bob@example.com
charlie@example.com

一个 JOIN 子句用于根据两个或多个表之间的相关列来组合它们的行。最常见的类型是 INNER JOIN,它返回在两个表中都有匹配值的记录。

这是经典的用例。您有一个 customers 表和一个 orders 表。要查看哪个客户下了哪个订单,您需要通过它们的公共字段(customers 表中的 id 和 orders 表中的 customer_id)将它们连接起来。

-- 表:customers
-- +----+--------+
-- | id | name |
-- +----+--------+
-- | 1 | Alice |
-- | 2 | Bob |
-- +----+--------+
-- 表:orders
-- +----------+-------------+--------------+
-- | order_id | customer_id | product |
-- +----------+-------------+--------------+
-- | 101 | 2 | Laptop |
-- | 102 | 1 | Mouse |
-- | 103 | 2 | Keyboard |
-- +----------+-------------+--------------+
-- JOIN 查询:
SELECT c.name, o.product
FROM customers AS c
INNER JOIN orders AS o ON c.id = o.customer_id;

结果结合了来自两个表的列,创建了一个更宽、信息更丰富的数据集。

nameproduct
BobLaptop
AliceMouse
BobKeyboard
方面UNIONJOIN
目的将两个或多个结果集中的行组合成一个单一集合。根据相关键组合来自两个或多个表的列。
数据方向垂直追加数据(使结果变长)。水平追加数据(使结果变宽)。
规则要求相同数量的列和兼容的数据类型。需要一个定义关系的连接条件(例如 ON 子句)。
重复项处理默认情况下,UNION 会移除重复项。UNION ALL 允许重复项。根据连接条件返回所有匹配的行;重复项不会被固有地移除。
结果列使用第一个 SELECT 语句中的列名。结果集包含所有连接表中的列。
  • 何时使用 UNION: 当您想组合来自不同表或查询的类似事物的列表时。例如,从 customers、suppliers 和 employees 表中获取所有联系电话号码的列表。
  • 何时使用 JOIN: 当您想通过添加其他表中的相关信息来丰富数据时。例如,查找购买了特定产品(orders 表)的客户姓名(customers 表)。