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

37 浏览
0 Comments

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

此外,LEFT OUTER JOINRIGHT OUTER JOINFULL OUTER JOIN 是如何安排的?

admin 更改状态以发布 2023年5月23日
0
0 Comments

对我来说,维恩图并没有什么用处。

它们没有显示交叉联接和内部联接之间的区别,例如,或者更普遍地显示任何不同类型的联接谓词之间的区别,也没有提供一个比较它们将如何操作的框架。

没有什么可以代替理解逻辑处理,而且相对容易理解。

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

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

我将从一个动画版本的全外部联接开始。接下来有进一步的解释。

enter image description here


解释

源表

enter link description here

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

SELECT A.Colour, B.Colour FROM A CROSS JOIN B

enter link description here

内连接和外连接有一个“ON”从句谓词。
- 内连接:对交叉连接结果中的所有行计算“ON”从句中的条件。如果结果为真,则返回连接行。否则将其丢弃。
- 左外连接:与内连接相同,然后对左表中未匹配任何内容的任何行,在右表列中输出这些为空值。
- 右外连接:与内连接相同,然后对右表中未匹配任何内容的任何行,在左表列中输出这些为空值。
- 全外连接:与内连接相同,然后像左外连接一样保留左侧未匹配的行,像右外连接一样保留右侧未匹配的行。

一些示例:
- SELECT A.Colour, B.Colour FROM A INNER JOIN B ON A.Colour = B.Colour:这是经典的等值连接。
- SELECT A.Colour, B.Colour FROM A INNER JOIN B ON A.Colour NOT IN('Green','Blue'):内连接条件不一定是相等条件,也不一定引用两个表格(甚至是任何一个)中的列。 对交叉连接返回的每一行计算'A.Colour NOT IN('Green','Blue')'。

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 IS NULL

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

重要的是为IS NULL测试选择一个不可空的列,或者确保连接条件排除任何NULL值,以使此模式正常工作并避免仅将具有在该列中具有NULL值的行带回,而不是未匹配的行。

loj is null

SELECT A.Colour, B.Colour FROM A RIGHT OUTER JOIN B ON A.Colour = B.Colour

右外连接的操作方式与左外连接类似,只是它们保留右表中不匹配的行并对左侧列进行空值扩展。

ROJ

SELECT A.Colour, B.Colour FROM A FULL OUTER JOIN B ON 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) AS Colour FROM A FULL OUTER JOIN B ON 1 = 0

稍加修改前面的查询,就可以模拟两个表的UNION ALL

UNION ALL

SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour = 'Green'

请注意,WHERE子句(如有)逻辑上在连接后运行。一种常见的错误是执行左外连接,然后在右表上包含带有条件的WHERE子句,这最终会排除不匹配的行。上述查询执行外连接…

LOJ

…然后运行“Where”子句。NULL= 'Green'不会返回true,因此由外部连接保留的行最终被丢弃(以及蓝色的行),有效地将连接转换回内部连接。

LOJtoInner

如果意图是只包含颜色为绿色的B行以及所有A行,不管正确的语法是什么

SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour AND B.Colour = 'Green'

enter image description here

SQL Fiddle

请查看这些示例,在SQLFiddle.com上实时运行

0
0 Comments

假设您在没有重复列的情况下连接,这是非常常见的情况:

  • A和B的内连接给出A与B的交集,即维恩图的内部部分。

  • A和B的外连接给出了A和B的联合,即维恩图的外部部分。

例子

假设您有两个带有单个列的表,数据如下:

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

0