一尘不染

"INNER JOIN" 和"OUTER JOIN"有什么区别?

sql

此外LEFT JOIN,RIGHT JOIN和FULL JOIN适合吗?


阅读 205

收藏
2022-01-06

共2个答案

一尘不染

假设您加入没有重复的列,这是一个非常常见的情况:

  • A 和 B 的内部连接给出了 A 与 B 相交的结果,即[Venn diagram]相交的内部部分。
  • A 和 B 的外连接给出了 A 联合 B 的结果,即[Venn diagram]联合的外部部分。

例子

假设您有两个表,每个表有一列,数据如下:

A    B
-    -
1    3
2    4
3    5
4    6

请注意,(1,2) 是 A 独有的,(3,4) 是通用的,而 (5,6) 是 B 独有的。

内部联接

使用任一等效查询的内部联接给出两个表的交集,即它们共有的两行。

select * from a INNER JOIN b on a.a = b.b;
select a.*, b.*  from a,b where a.a = b.b;

a | b
--+--
3 | 3
4 | 4

左外连接

左外连接将给出 A 中的所有行,以及 B 中的所有公共行。

select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.*  from a,b where a.a = b.b(+);

a |  b
--+-----
1 | null
2 | null
3 |    3
4 |    4

右外连接

右外连接将给出 B 中的所有行,以及 A 中的所有公共行。

select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.*  from a,b where a.a(+) = b.b;

a    |  b
-----+----
3    |  3
4    |  4
null |  5
null |  6

全外连接

一个完整的外连接会给你 A 和 B 的联合,即 A 中的所有行和 B 中的所有行。如果 A 中的某些内容在 B 中没有相应的数据,则 B 部分为空,反之亦然反之。

select * from a FULL OUTER JOIN b on a.a = b.b;

 a   |  b
-----+-----
   1 | null
   2 | null
   3 |    3
   4 |    4
null |    6
null |    5
2022-01-06
一尘不染

维恩图并不适合我。

例如,它们没有显示交叉连接和内部连接之间的任何区别,或者更一般地显示不同类型的连接谓词之间的任何区别,或者提供一个框架来推理它们将如何操作。

理解逻辑处理是无可替代的,无论如何掌握起来都相对简单。

  1. 想象一个交叉连接。
  2. on针对步骤 1 中的所有行评估子句,保留谓词评估为的那些行true
  3. (仅适用于外部联接)在步骤 2 中丢失的任何外部行中重新添加。

(注意:在实践中,查询优化器可能会找到比上面纯逻辑描述更有效的查询执行方式,但最终结果必须相同)

我将从一个完整的外连接的动画版本开始。进一步的解释如下。

在此处输入图片说明


解释

源表

在此处输入链接描述

首先从CROSS JOIN(又名笛卡尔积)开始。这没有ON子句,只是返回两个表中行的每个组合。

从 A CROSS JOIN B 中选择 A.Colour、B.Colour

在此处输入链接描述

内连接和外连接有一个“ON”子句谓词。

  • 内部联接。为交叉连接结果中的所有行评估“ON”子句中的条件。如果为 true,则返回连接的行。否则丢弃它。
  • 左外连接。与内部连接相同,然后对于左表中不匹配任何内容的任何行,将这些行输出为右表列的 NULL 值。
  • 右外连接。与内部连接相同,然后对于右表中不匹配任何内容的任何行,将这些行输出为左表列的 NULL 值。
  • 完全外连接。与内连接相同,然后保留左外连接中的左非匹配行和右外连接中的右非匹配行。

一些例子

SELECT A.Colour, B.Colour from A INNER JOIN B ON A.Colour = B.Colour

以上是经典的equi join。

内部联接

动画版

在此处输入图片说明

SELECT A.Colour, B.Colour from A INNER JOIN B ON A.Colour NOT IN (‘Green’,’Blue’)

内连接条件不一定是相等条件,也不需要引用来自两个(或什至其中一个)表的列。A.Colour NOT IN ('Green','Blue')对交叉连接返回的每一行进行评估。

内部 2

SELECT A.Colour, B.Colour from A INNER JOIN B ON 1 =1

对于交叉联接结果中的所有行,联接条件的计算结果为真,因此这与交叉联接相同。16行的图我就不重复了。

SELECT A.Colour, B.Colour from A LEFT OUTER JOIN B ON A.Colour = B.Colour

外连接的逻辑评估方式与内连接相同,不同之处在于如果左表中的一行(对于左连接)根本不与右手表中的任何行连接,它会保留在结果中,其NULL值为右手边的列。

LOJ

SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour 为 NULL

这只是将先前的结果限制为仅返回 where 的行B.Colour IS NULL。在这种特殊情况下,这些将是保留的行,因为它们在右侧表中没有匹配项,并且查询返回表中不匹配的单个红色行B。这被称为反半连接。

IS NULL测试选择一列不可为空或连接条件确保NULL将排除任何值以便此模式正常工作并避免仅带回恰好具有该NULL值的行很重要除了未匹配的行之外的列。

loj 为空

从 A.Colour = B.Colour 的右外部连接 B 中选择 A.Colour、B.Colour

右外连接的作用类似于左外连接,除了它们保留右表中不匹配的行并且 null 扩展左手列。

注册会计师

从 A.Colour = B.Colour 上的完全外部连接 B 中选择 A.Colour、B.Colour

全外连接结合了左右连接的行为,并保留了左右表中不匹配的行。

FOJ

SELECT A.Colour, B.Colour from A FULL OUTER JOIN B ON 1 = 0

交叉联接中没有任何行与1=0谓词匹配。两侧的所有行都使用普通外连接规则保留,另一侧表的列中为 NULL。

FOJ 2

SELECT COALESCE(A.Colour, B.Colour) 作为颜色从一个完整的外部连接 B ON 1 = 0

对前面的查询稍作修改,就可以模拟UNION ALL两个表中的一个。

联合所有

SELECT A.Colour, B.Colour 从 A.Colour = B.Colour WHERE B.Colour = ‘Green’ 上的 A LEFT OUTER JOIN B

请注意,WHERE子句(如果存在)在连接之后在逻辑上运行。一个常见的错误是执行左外连接,然后在右表上包含一个 WHERE 子句,该子句最终排除了不匹配的行。以上最终执行外连接......

LOJ

…然后“Where”子句运行。NULL= 'Green'不评估为真,因此外部连接保留的行最终被丢弃(连同蓝色)有效地将连接转换回内部连接。

LOJ到内部

如果意图是仅包括来自 B 的行,其中颜色为绿色,而不管正确的语法是来自 A 的所有行

从 A.Colour = B.Colour AND B.Colour = ‘Green’ 上的 A LEFT OUTER JOIN B 中选择 A.Colour、B.Colour

在此处输入图片说明

2022-01-06