Sql 作为维恩图连接

我在理解 sql 中的连接时遇到了困难,我想这个图像可能会对我有所帮助。问题是我不完全理解。例如,图像右上角的联接,它将整个 B 圆涂成红色,但只将与 A 的重叠部分涂成红色。这幅图像让人觉得圆圈 B 是 sql 语句的主要焦点,但是 sql 语句本身,通过从 A 开始(从 A 中选择,连接 B) ,给我传达了相反的印象,即 A 将是 sql 语句的焦点。

类似地,下面的图像只包含来自 B 圆的数据,那么为什么在 join 语句中包含 A 呢?

问题: 从右上角顺时针方向工作,在中间完成,可以有人提供更多关于每个 sql 图像表示的信息,解释

A)为什么在每种情况下都需要连接(例如,特别是在没有从 A 或 B 获取数据的情况下,例如只有 A 或 B 而不是两者都有颜色的情况下)

B)以及任何其他能够说明为什么图像能够很好地表示 sql 的细节

sql join diagram

120910 次浏览

我认为您主要的潜在困惑是,当(例如)只有 A以红色突出显示时,您认为这意味着“查询只返回数据 A”,但实际上它意味着“查询只返回数据 对于那些 A有记录的案例”。查询可能仍然包含来自 B 的数据(对于 B没有记录的情况,查询将替换 NULL)

类似地,下面的图像只包含来自 B 圆的数据,那么为什么在 join 语句中包含 A 呢?

如果你指的是 A完全是白色的图像,而且 B的部分有一个红色的新月形,与 A没有重叠,那么: A出现在查询中的原因是,A是如何在 B中找到需要排除的记录。(如果查询中没有出现 A,那么维恩图就不会有 A,它只会显示 B,并且没有办法区分所需的记录和不需要的记录。)

这幅图像让人觉得圆圈 B 是 sql 语句的主要焦点,但是 sql 语句本身,通过从 A 开始(从 A 中选择,连接 B) ,给我传达了相反的印象,即 A 将是 sql 语句的焦点。

非常正确。由于这个原因,RIGHT JOIN是相对不常见的; 虽然使用 LEFT JOIN的查询几乎总是可以重新排序使用 RIGHT JOIN(反之亦然) ,但通常人们使用 LEFT JOIN而不是 RIGHT JOIN编写查询。

当您进行联接时,您的两个表可能不能完全匹配。具体来说,A 中可能有一些行与 B 中的任何行都不匹配,或者 A 中的重复行与 B 中的单个行匹配,反之亦然。

当这种情况发生时,你有一个选择:

  1. 对于每一个 A,如果有的话,取一个有效的 B。(左上)
  2. 取完全匹配的每一对(丢弃任何丢失的 A 或 B ——中心)
  3. 对于每个 B,取一个有效的 A,如果有的话(右上)
  4. 拿走所有东西(左下角)

从技术上来说,左中心和右中心是连接,但是它们是无意义的; 它们可以更有效地编写 SELECT <select_list> FROM TableA A WHERE A.Key NOT IN (SELECT B.Key FROM TableB B)(或者相反)。

为了直接回答你的困惑,RIGHT JOIN说“下面的表达式是这个查询的重点”。 右下角有点奇怪,我不明白你为什么要那样做。它返回两个外部中间查询的结果,这两个查询与对应表的所有列中的 NULL混合在一起。

对于正确的连接,是的,语法可能会令人困惑,但是是的,它就是它看起来的样子。当您说“ TableA RIGHT JOIN TableB”时,它实际上是说 TableB 是您所引用的主表,而 TableA 只是挂在它具有匹配记录的地方。这在查询中读起来很奇怪,因为 TableA 被列在第一位,所以大脑会自动为它分配更多的优先级,即使 TableB 确实是查询中更重要的表。由于这个原因,您很少在实际代码中看到正确的连接。

因此,让我们用两个容易记录的东西来代替 A 和 B。假设我们有两张表来记录人们的信息,鞋码和智商。你有一些人的鞋码信息,一些人的智商信息。并且在两个表上都有一个 PersonID,您可以加入它们。

顺时针从右上角开始(即使这是从一些更复杂和人为的情况开始) :

  • 给我所有的智商信息。包括任何鞋码的人,如果我们有它的信息。
  • 鞋码右连接 IQ 显示大小。PersonID = NULL-> 给我所有的智商信息,但仅限于那些没有任何鞋码信息的人
  • 鞋码全外连接。PersonID = NULL AND IQ. PersonID = NULL-> 给我鞋码信息,只给那些没有 IQ 信息的人,加上那些没有鞋码信息的人的 IQ 信息
  • 给我所有的东西,所有的鞋码和所有的 IQ 数据。如果任何鞋码和 IQ 记录具有相同的 PersonID,请将它们包括在一行中。
  • 给我所有的鞋码信息,但仅限于那些没有智商信息的人
  • 给我所有的鞋码信息。包括那些人的智商信息,如果我们有的话。

维恩图适用于表示集合操作,如 UNION、 INTERSECTS、 EXCEPT 等。

只有在诸如 EXCEPT 之类的设置操作使用诸如 LEFT JOIN WHERE rhs.KEY 为 NULL 之类的内容进行模拟的情况下,这个图才是准确的。

否则就是误导。例如,如果连接条件不是1:1,则任何连接都可能导致行相乘。但是集合只允许包含不同的成员,因此这些成员不能表示为集合操作。

然后是 CROSS JOIN 或 INNER JOIN ON 1 = 1-这既不类似于图中所示的 INNER JOIN,也不能用维恩图真正描述生成的集合。更不用说其他所有可能的三角连接,自连接和反连接,比如:

lhs INNER JOIN rhs ON rhs.VALUE < lhs.VALUE (triangular)

或者

SELF self1
INNER JOIN SELF self2
ON self2.key <> self1.key
AND self1.type = self2.type

(自交叉和反连接寻找除自己以外的所有相似的家庭成员-自我1和自我2是相同的集合,其结果是一个适当的子集)

在教程的前几分钟,坚持使用键上的连接可能没有问题,但是这可能会导致学习连接内容的方法很糟糕。我想这就是你发现的。

Venn Diagram 通常以这种方式表示 JOIN 的想法需要消失。

我同意凯德关于维恩图的局限性。一个更合适的视觉表示可能是这样的。

桌子

Tables

从交叉连接中选择 A 颜色,B 颜色

交叉连接(或笛卡儿积连接)产生的结果是两个表中每一行的组合。每个表有4行,因此结果中有16行。

Cross Join

从 A 上的内连接中选择 A 颜色,B 颜色 B 颜色 = B 颜色 SQL Fiddle

内部联接在逻辑上返回来自交叉联接的所有符合联接条件的行。在这种情况下,五个做。

Inner Join

选择 A 颜色,B 颜色来自 A 内部连接 B 颜色不在(“绿色”,“蓝色”) SQL Fiddle

内部连接条件不一定是相等条件,也不需要同时引用两个表中的列(或者两个表中的任何一个)。对交叉连接的每一行计算 A.Colour NOT IN ('Green','Blue')将返回。

inner 2

对于交叉连接中的每一行,1=1的内部连接条件的值将为 true,因此两者是等价的(SQL Fiddle)。

从 A 上的一个左外连接中选择 A 颜色,B 颜色

外部连接的逻辑计算方式与内部连接相同,只是如果左表中的一行(对于左连接)根本没有与右表中的任何行连接,则在结果中保留右列的 NULL值。

LOJ

从 A.Color = B.Color 中的一个左外连接 B 中选择 A.Color,B.Color,其中 B.Color 为 NULL SQL Fiddle

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

重要的是为 IS NULL测试选择一个不为空的列,或者连接条件确保任何 NULL值将被排除在外,以便这个模式正常工作,并避免只带回碰巧有该列的 NULL值的行,以及未匹配的行。

loj is null

从 A 上的右外连接中选择 A 颜色,B 颜色

右外部连接的作用与左外部连接类似,只是它们保留了右表中的非匹配行,并且 null 扩展了左侧列。

ROJ

从 A 上的完整外连接中选择 A 颜色,B 颜色 B 颜色 = B 颜色 SQL Fiddle

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

FOJ