MySQL 连接方式:内连接、外连接、左连接、右连接、交叉连接

⚡ 智能摘要

MySQL 连接(JOIN)将两个或多个相关表中的行合并到一个结果集中。本资源通过可运行的查询、示例数据和清晰的输出表,讲解了交叉连接(CROSS JOIN)、内连接(INNER JOIN)、左连接(LEFT JOIN)、右连接(RIGHT JOIN)和外连接(OUTER JOIN),以帮助读者进行实际的数据库操作。

  • 🔗 核心原则: JOIN 操作使用主键和外键关系将不同表中的行匹配起来。
  • 为何重要: 一次 JOIN 查询利用索引,减少了服务器往返次数,相比多次单独查询,效果更佳。
  • ✖️ 交叉连接行为: 第一个表格的每一行都与第二个表格的每一行一一对应,形成一个笛卡尔积。
  • 🎯 内部 JOIN 行为: 仅返回两个表中均满足匹配条件的行。
  • ↔️ 外部连接行为: LEFT JOIN 和 RIGHT JOIN 也会返回不匹配的行,并将缺失的列填充为 NULL。
  • 🧩 ON 与 USING: USING 要求列名必须完全相同,而 ON 支持任何匹配表达式。

MySQL JOINS

什么是 JOINS?

连接有助于从两个或多个数据库表中检索数据。

这些表使用主键和外键相互关联。

注意:JOIN 是 SQL 学习者中最容易误解的概念之一。为了简单易懂,我们将使用一个新的数据库来进行练习。如下所示。

以下所有示例均使用这两个表格。 电影 ID 列在 成员 指向 id 列在 电影 — 每个 JOIN 匹配的关系。

成员

id 名字 电影 ID
1 Adam SMITH 1
2 拉维 库马尔 2
3 Susan 戴维森 5
4 珍妮 阿德里安娜 8
5 10

电影

id 标题 类别
1 刺客信条:余烬 动画
2 铁甲钢拳(2012) 动画
3 艾尔文与花栗鼠 动画
4 丁丁历险记 动画
5 安全 (2012) 操作
6 安全屋(2012) 操作
7 GIA 18+
8 截止日期2009 18+
9 肮脏的图片 18+
10 马利和我 浪漫

为什么要使用 JOIN?

在了解每种 JOIN 类型之前,有必要了解为什么 JOIN 比运行多个查询更可取。

现在你可能会想,既然我们可以运行查询来完成同样的任务,为什么还要使用 JOIN。特别是如果你有数据库编程经验,你就会知道我们可以逐个运行查询,在连续的查询中使用每个查询的输出。当然,这是可能的。但是使用 JOIN,你只需使用一个带有任何搜索参数的查询就可以完成工作。另一方面 MySQL 可以实现更好的性能 使用 JOIN 因为它可以使用索引。只需使用单个 JOIN 查询而不是运行多个查询即可减少服务器开销。使用多个查询会导致在 MySQL 和应用程序(软件)。此外,它还需要在应用程序端进行更多的数据操作。

显然,我们可以取得更好的成绩 MySQL 并通过使用 JOIN 来提高应用程序的性能。

连接类型

MySQL 支持多种 JOIN 类型,每种类型都针对同一对表的不同问题进行解答。下表对它们进行了比较;每种类型都通过一个查询及其输出进行了演示。

连接类型 返回的行 结果中是否包含空值? 典型用途
交叉加入 表A的每一行都与表B的每一行配对。 没有 生成所有可能的组合
INNER JOIN 仅保留两个表中均符合条件的行 没有 实际租借过电影的会员
LEFT JOIN 左侧表格中的所有行,加上右侧表格中的匹配项 是的,在右边 所有电影,甚至包括那些从未出租过的。
正确加入 右侧表格中的所有行,加上左侧表格中的匹配项 是的,在左侧 所有电影,即使没有附属成员

交叉加入

交叉连接 (Cross JOIN) 是连接 (JOIN) 的最简单形式,它将一个数据库表的每一行与另一个数据库表的所有行进行匹配。

换句话说,它为我们提供了第一个表的每一行与第二个表中的所有记录的组合。

假设我们想要获取所有电影记录的所有会员记录,我们可以使用下面显示的脚本来获得我们想要的结果。

联接类型

SELECT * FROM `movies` CROSS JOIN `members`

在以下位置执行上述脚本 MySQL 工作台 给出了以下结果。

id title id first_name last_name movie_id
1 ASSASSIN'S CREED: EMBERS Animations 1 Adam Smith 1
1 ASSASSIN'S CREED: EMBERS Animations 2 Ravi Kumar 2
1 ASSASSIN'S CREED: EMBERS Animations 3 Susan Davidson 5
1 ASSASSIN'S CREED: EMBERS Animations 4 Jenny Adrianna 8
1 ASSASSIN'S CREED: EMBERS Animations 6 Lee Pong 10
2 Real Steel(2012) Animations 1 Adam Smith 1
2 Real Steel(2012) Animations 2 Ravi Kumar 2
2 Real Steel(2012) Animations 3 Susan Davidson 5
2 Real Steel(2012) Animations 4 Jenny Adrianna 8
2 Real Steel(2012) Animations 6 Lee Pong 10
3 Alvin and the Chipmunks Animations 1 Adam Smith 1
3 Alvin and the Chipmunks Animations 2 Ravi Kumar 2
3 Alvin and the Chipmunks Animations 3 Susan Davidson 5
3 Alvin and the Chipmunks Animations 4 Jenny Adrianna 8
3 Alvin and the Chipmunks Animations 6 Lee Pong 10
4 The Adventures of Tin Tin Animations 1 Adam Smith 1
4 The Adventures of Tin Tin Animations 2 Ravi Kumar 2
4 The Adventures of Tin Tin Animations 3 Susan Davidson 5
4 The Adventures of Tin Tin Animations 4 Jenny Adrianna 8
4 The Adventures of Tin Tin Animations 6 Lee Pong 10
5 Safe (2012) Action 1 Adam Smith 1
5 Safe (2012) Action 2 Ravi Kumar 2
5 Safe (2012) Action 3 Susan Davidson 5
5 Safe (2012) Action 4 Jenny Adrianna 8
5 Safe (2012) Action 6 Lee Pong 10
6 Safe House(2012) Action 1 Adam Smith 1
6 Safe House(2012) Action 2 Ravi Kumar 2
6 Safe House(2012) Action 3 Susan Davidson 5
6 Safe House(2012) Action 4 Jenny Adrianna 8
6 Safe House(2012) Action 6 Lee Pong 10
7 GIA 18+ 1 Adam Smith 1
7 GIA 18+ 2 Ravi Kumar 2
7 GIA 18+ 3 Susan Davidson 5
7 GIA 18+ 4 Jenny Adrianna 8
7 GIA 18+ 6 Lee Pong 10
8 Deadline(2009) 18+ 1 Adam Smith 1
8 Deadline(2009) 18+ 2 Ravi Kumar 2
8 Deadline(2009) 18+ 3 Susan Davidson 5
8 Deadline(2009) 18+ 4 Jenny Adrianna 8
8 Deadline(2009) 18+ 6 Lee Pong 10
9 The Dirty Picture 18+ 1 Adam Smith 1
9 The Dirty Picture 18+ 2 Ravi Kumar 2
9 The Dirty Picture 18+ 3 Susan Davidson 5
9 The Dirty Picture 18+ 4 Jenny Adrianna 8
9 The Dirty Picture 18+ 6 Lee Pong 10
10 Marley and me Romance 1 Adam Smith 1
10 Marley and me Romance 2 Ravi Kumar 2
10 Marley and me Romance 3 Susan Davidson 5
10 Marley and me Romance 4 Jenny Adrianna 8
10 Marley and me Romance 6 Lee Pong 10

INNER JOIN

CROSS JOIN 会返回所有可能的配对,这通常不是你想要的。INNER JOIN 则会将结果缩小到真正相关的配对。

内部 JOIN 用于返回两个表中满足给定条件的行。

假设你想获取所有租过电影的会员列表以及他们租过的电影名称。你可以简单地使用 INNER JOIN 来实现,它会返回两个表中满足给定条件的行。

INNER JOIN

SELECT members.`first_name` , members.`last_name` , movies.`title`
FROM members ,movies
WHERE movies.`id` = members.`movie_id`

执行上述脚本

first_name last_name title
Adam Smith ASSASSIN'S CREED: EMBERS
Ravi Kumar Real Steel(2012)
Susan Davidson Safe (2012)
Jenny Adrianna Deadline(2009)
Lee Pong Marley and me

注意上述结果脚本也可以按如下方式编写以实现相同的结果。

SELECT A.`first_name` , A.`last_name` , B.`title`
FROM `members` AS A
INNER JOIN `movies` AS B
ON B.`id` = A.`movie_id`

外连接

INNER JOIN 会静默删除没有匹配项的行。当这些未匹配的行很重要时,OUTER JOIN 才是正确的选择。

MySQL 外连接会返回两个表中所有匹配的记录。

它可以检测连接表中没有匹配的记录。它返回 如果没有找到匹配项,则为连接表的记录的值。

听起来很复杂?我们来看一个例子——

LEFT JOIN

假设现在你想获取所有电影的标题以及租借过这些电影的会员姓名。很明显,有些电影还没有被任何人租借。我们可以简单地使用 LEFT JOIN 为目的。

外连接

即使在右侧表中未找到匹配的行,LEFT JOIN 也会返回左侧表中的所有行。 如果在右侧的表中未找到任何匹配项,则返回 NULL。

SELECT A.`title` , B.`first_name` , B.`last_name`
FROM `movies` AS A
LEFT JOIN `members` AS B
ON B.`movie_id` = A.`id`

在以下位置执行上述脚本 MySQL 工作台返回的结果如下所示。对于未被租借的电影,成员名称字段的值为 NULL。这意味着在成员表中没有找到与该电影匹配的成员。

title first_name last_name
ASSASSIN'S CREED: EMBERS Adam Smith
Real Steel(2012) Ravi Kumar
Safe (2012) Susan Davidson
Deadline(2009) Jenny Adrianna
Marley and me Lee Pong
Alvin and the Chipmunks NULL NULL
The Adventures of Tin Tin NULL NULL
Safe House(2012) NULL NULL
GIA NULL NULL
The Dirty Picture NULL NULL
Note: Null is returned for non-matching rows on right

正确加入

RIGHT JOIN 显然与 LEFT JOIN 相反。即使在左侧表中未找到匹配的行,RIGHT JOIN 也会返回右侧表中的所有列。如果在左侧表中未找到匹配项,则返回 NULL。

在我们的示例中,假设您需要获取会员的姓名以及他们租借的电影。现在我们有一位新会员,他还没有租借任何电影

正确加入

SELECT A.`first_name` , A.`last_name`, B.`title`
FROM `members` AS A
RIGHT JOIN `movies` AS B
ON B.`id` = A.`movie_id`

在以下位置执行上述脚本 MySQL 工作台给出以下结果。

first_name last_name title
Adam Smith ASSASSIN'S CREED: EMBERS
Ravi Kumar Real Steel(2012)
Susan Davidson Safe (2012)
Jenny Adrianna Deadline(2009)
Lee Pong Marley and me
NULL NULL Alvin and the Chipmunks
NULL NULL The Adventures of Tin Tin
NULL NULL Safe House(2012)
NULL NULL GIA
NULL NULL The Dirty Picture
Note: Null is returned for non-matching rows on left

“ON” 和 “USING” 子句

到目前为止,每个查询都匹配到了带有 ON 子句的行。 MySQL 当匹配的列共享名称时,提供更简洁的替代方案。

在上面的 JOIN 查询示例中,我们使用了 ON 子句来匹配表之间的记录。

USING 子句也可用于相同目的。 使用两个表中匹配的列需要具有相同的名称。

到目前为止,我们在“movies”表中使用名为“id”的主键。我们在“members”表中使用名为“movie_id”的主键。

让我们将“电影”表的“id”字段重命名为“movie_id”。我们这样做是为了获得完全相同的匹配字段名称。

ALTER TABLE `movies` CHANGE `id` `movie_id` INT( 11 ) NOT NULL AUTO_INCREMENT;

接下来让我们将 USING 与上面的 LEFT JOIN 示例一起使用。

SELECT A.`title` , B.`first_name` , B.`last_name`
FROM `movies` AS A
LEFT JOIN `members` AS B
USING ( `movie_id` )

除了使用 ON与 JOIN 一起使用 你可以使用许多其他 MySQL 类似条款 通过...分组, 在哪里 甚至像 SUM, AVG等等。

常见问题

JOIN 操作将两个表中的列并排合并,并根据键匹配行。UNION 操作将两个查询的结果垂直堆叠,并且要求列数和类型完全匹配。

是的。可以链接多个 JOIN 子句,每个子句都有自己的 ON 条件。 MySQL 将前两个表连接起来,然后将中间结果连接到下一个表,依此类推。

自连接(SELF JOIN)使用两个别名将一个表与其自身连接起来。它比较一个表中的行,例如将员工行与其经理的行进行匹配。

是的。内置于编辑器中的人工智能助手,例如…… MySQL 工作台 可以根据纯文本提示编写 JOIN 查询。务必检查生成的 ON 条件,因为错误的键会导致错误的结果,即使这些结果没有实际意义。

部分如此。AI顾问会建议索引和更优的连接顺序,这通常可以缩短执行时间。但最终的执行计划仍然由优化器决定,因此连接键的正确索引仍然是最重要的因素。

总结一下这篇文章: