MySQL 性能:SQL 中的 JOIN 简介

在本文中,我们将学习在 SQL 中连接表的基础知识。 我们将了解 Left、Right、Inner 和 Outer JOIN,并举例说明如何使用它们。

RDBMS(关系数据库管理系统)中的数据被分组到表中。 这些表对可以存储在其中的数据类型有严格的定义。 为了连接不同的表,从而连接可能相互关联的不同类型的数据,我们将使用 JOIN 子句。

JOIN 的类型

JOIN 有四种基本类型:INNER、OUTER、LEFT 和 RIGHT。 连接两个表时,它们将根据 ON 子句中的条件分别返回相应表的不同子集。

  • LEFT 和 RIGHT JOIN 执行类似的任务。 它们都返回整个单个表,其中包含与第二个表相关的信息。
  • INNER JOIN 和 OUTER JOIN 执行非常不同的任务。 INNER JOIN 产生的结果非常有限,而 OUTER 返回完整的数据集。

注意:在撰写本文时,MariaDB 和 MySQL 不支持 OUTER JOIN。 然而,我们将提供一个 example 一种以不同方式产生此输出的方法。

在这个 example,我们正在使用 example 本教程的销售部门,使用三个表:销售人员、订单和客户。

salespeople 表将包含三列:id、name 和佣金率。

销售员表

接下来,订单表将包含四列:订单 ID、订单总成本、客户以及销售人员(如果有)。

订单表

客户表将包含两列:id 和基本联系信息。

客户表12-19客户表

所以,我们现在有多个信息表,它们以不同的方式对不同的人有用。 使用这三个表(销售人员、订单和客户),我们将提供每个 JOIN 可能如何有用的示例。

左连接

可能最常用的 JOIN 类型是 LEFT JOIN。 如果您想到要连接的两张表,FROM 子句中提到的那一张在左边。 JOIN 子句中提到的那个在右边。 在 LEFT JOIN 中,LEFT(或 FROM)表中的每一行都在结果中返回,并与 RIGHT(或 JOIN)表中匹配 ON 子句的相应行链接。

请记住,左侧的某些行可能在右侧没有匹配的数据。 在这种情况下,将在结果中从 RIGHT 表中填写的字段将由 NULL 值填充。

此外,如果 RIGHT 表中的多行与 LEFT 表中的行匹配,则结果集中将包含多行。 维恩图显示了 LEFT JOIN 的可视化效果:

left-join-12-19左连接示例

营销总监要求您提供按客户细分的所有订单的报告。 您可以为此使用 LEFT JOIN:

SELECT *
FROM orders
LEFT JOIN customer
ON orders.customer_id = customer.id;

此查询要求“订单”表中与“客户”表中的行链接的所有数据,其中客户的 ID 等于订单中的客户 ID。 结果将如下所示:

订单表2-12-19

请注意,对于 Widgets LLC 客户,有三个条目,因为他们有三个订单。 Jolly Inc. 下了两份订单,Acme Inc. 下了一份。 由于没有下订单,因此 Cheapo 未出现在此列表中。

正确加入

RIGHT JOIN 与 LEFT JOIN 非常相似,不同之处在于它返回 RIGHT (JOIN) 表中的每一行,并且只返回 LEFT (FROM) 表中的相应行。 同样,如果 LEFT 表中没有数据,那么这些列将填充 NULL 值。

如果 LEFT 表中有多行,则结果集中将有多行。 它的维恩图看起来像这样:

右加入 12-19一个 example 正确的加入

如果管理层希望与每个客户一起报告; 即使他们没有下订单,我们也可以使用 RIGHT JOIN。

SELECT *
FROM orders
RIGHT JOIN customer
ON orders.customer_id = customer.id;

我们再次从“订单”表开始并将其加入到客户表中。 因为我们使用了 RIGHT JOIN,所以我们将为 RIGHT (JOIN) 表中的每个条目获得至少一行,customer。 当 customer.id 和 orders.customer_id 之间存在匹配时,则填写信息。结果包括在 order 列中具有 NULL 值的 Cheapo Co:

右连接表 12-19

内部联接

INNER JOIN 仅返回每列中与 ON 子句匹配的行。 如果 RIGHT 上没有匹配项,则排除 LEFT 中的行,反之亦然。 INNER JOIN 的维恩图如下所示:

内部连接 ​​12-19一个 example INNER JOIN 的

现在是发薪日,工资部门需要知道要支付多少佣金。 为此,他们需要知道通过每个销售人员下达的订单。 请注意,并非所有订单都通过销售人员,所以我们不关心这些。 为此,我们可以使用 INNER JOIN:

SELECT *,cost * commission_rate / 100 AS commission_amount
FROM orders
INNER JOIN salespeople
ON orders.salesperson_id = salespeople.id;

我们再次从订单表开始。 这次我们将它与 salespeople 表连接起来。 如果orders 表中有一个条目与salespeople 表中的条目匹配,那么该行将被包括在内。 不是用 NULL 值填充不匹配的行,而是在结果中忽略这些行。

请注意,我们告诉数据库不仅要返回销售金额和佣金率,还要返回计算的佣金。 结果将如下所示:

外连接0-12-19

外连接

无论是否匹配,OUTER JOIN 都会返回所有内容。 如果你要结合 LEFT 和 RIGHT JOIN 的结果,你会得到一个 OUTER JOIN。 OUTER JOIN 的维恩图如下所示:

外连接 12-19一个 example 使用 OUTER JOIN

现在是月底,销售经理想知道所有的销售额以及支付的所有佣金。 为此,我们将使用 OUTER JOIN:

SELECT *,cost * commission_rate / 100 AS commission_amount
FROM orders
FULL OUTER JOIN salespeople
ON orders.salesperson_id = salespeople.id;

与工资单报告一样,我们从订单开始,然后加入销售人员。 不同之处在于,使用 OUTER JOIN 您将从 LEFT 和 RIGHT 表中获得结果,其中填充了 NULL ,而没有相应的匹配项。 结果如下所示:

外连接3-12-19

现在,请记住我们说过 MariaDB 和 MySQL 不支持 OUTER JOIN。 我们还说过,如果您将 LEFT JOIN 添加到 RIGHT JOIN,您将得到一个 OUTER JOIN。 这两个系统的诀窍就是做到这一点。 我们使用 UNION 子句来实现这一点。 它将一个查询的结果添加到另一个:

SELECT *,cost * commission_rate / 100 AS commission_amount
FROM orders
LEFT JOIN salespeople
ON orders.salesperson_id = salespeople.id
UNION
SELECT *,cost * commission_rate / 100 AS commission_amount
FROM orders
RIGHT JOIN salespeople
ON orders.salesperson_id = salespeople.id;

结果将如下所示:

外连接4-12-19

多个联接

JOIN 还允许您连接两个以上的表。 如果我们想要一份包含客户和销售人员信息的完整销售报告,我们只需在最后再做一次 JOIN。

SELECT *
FROM orders
LEFT JOIN salespeople
ON orders.salesperson_id = salespeople.id
LEFT JOIN customer
ON customer.id = orders.customer_id;

在这个 example,我们从 orders 表开始,并将其连接到 salespeople 表,就像我们之前所做的一样。 下一步是将表连接到客户表。 这将填写可链接到订单表的所有信息。

多连接 12-19

本文只是一个简短的介绍,并不打算详尽讨论如何在 SQL 中使用 JOIN。

点击下面今天使用这个方便的优惠券!

Liquid Web 拥有一些业内最强大的数据库服务器。 这些服务器可用于为企业规模的公司运行最小的家庭业务到最大的多数据库集群。

给我们打电话 800.580.4985,或打开 聊天 或与我们联系,与我们经验丰富的解决方案或托管顾问之一交谈,了解您今天如何利用这些技术!