sql作为维恩图加入

问题描述 投票:40回答:5

我在理解sql中的连接时遇到了麻烦,并且遇到了这个我认为可能对我有用的图像。问题是我不完全理解它。例如,图像右上角的连接,它将整个B圆圈的颜色设置为红色,但只有A的重叠。图像使得它看起来像圆圈B是sql语句的主要焦点,但是sql语句本身,从A开始(从A中选择,加入B),向我传达了相反的印象,即A将成为sql语句的焦点。

同样,下面的图像只包含来自B圈的数据,那么为什么在连接语句中包含A呢?

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

a)为什么在每种情况下都需要连接(例如,特别是在没有数据来自A或B的情况下,即只有A或B而不是两者都被着色的情况)

b)以及任何其他细节可以澄清为什么图像是sql的良好表示

sql mysqli visualization set-theory
5个回答
8
投票

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

同样,下面的图像只包含来自B圈的数据,那么为什么在连接语句中包含A呢?

如果你的意思是 - A完全是白色的图像,并且B部分的红色新月形状与A不重叠,那么:A出现在查询中的原因是,A是它的发现方式B中需要排除的记录。 (如果A没有出现在查询中,那么维恩图不会有A,它只会显示B,并且没有办法将所需的记录与不需要的记录区分开来。)

图像看起来像圆圈B是sql语句的主要焦点,但是sql语句本身,从A开始(从A中选择,加入B),给我带来了相反的印象,即A将成为焦点的SQL语句。

完全正确。因此,RIGHT JOINs相对不常见;虽然使用LEFT JOIN的查询几乎总是可以重新排序以使用RIGHT JOIN(反之亦然),但通常人们会使用LEFT JOIN而不是RIGHT JOIN编写查询。


52
投票

我同意Cade关于维恩图的局限性。更合适的视觉表现可能就是这样。

Tables

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

交叉连接(或笛卡尔积)使用两个表中的每个行组合生成结果。每个表有4行,因此在结果中产生16行。

SELECT A.Colour, B.Colour FROM A INNER JOIN B ON A.Colour = B.Colour SQL Fiddle

内部联接在逻辑上返回交叉连接中与连接条件匹配的所有行。在这种情况下,五个。

SELECT A.Colour, B.Colour FROM A INNER JOIN B ON A.Colour NOT IN ('Green','Blue') SQL Fiddle

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

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

SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour SQL Fiddle

外连接的逻辑评估方式与内连接的方式相同,只是如果左表中的一行(对于左连接)没有与右表中的任何行连接,它将保留在结果中,其中NULL值为右栏。

SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour IS NULL SQL Fiddle

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

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

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

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

SELECT A.Colour, B.Colour FROM A FULL OUTER JOIN B ON A.Colour = B.Colour SQL Fiddle

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


10
投票

维恩图适用于表示集合操作,如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

(自我交叉和反连接以找到除了你自己以外的所有类似的家庭成员 - self1和self2是相同的集合,结果是一个合适的子集)

在教程的前几分钟坚持连接键可能没问题,但这可能会导致学习连接的路径很差。我想这就是你找到的。

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


-1
投票

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

发生这种情况时,您可以选择:

  1. 对于每个A,如果有一个B,则采用一个有效的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混合在一起。


-1
投票

对于正确的连接,是的,语法可能令人困惑,但是它似乎是它的样子。当你说“TableA RIGHT JOIN TableB”时,确实说TableB是你所指的主表,而TableA只挂在它有匹配记录的地方。这在查询中读取很奇怪,因为TableA首先被列出,所以你的大脑会自动为它分配更多优先级,即使TableB确实是查询中更重要的表。因此,您很少在实际代码中看到正确的连接。

因此,不要使用A和B,而是采取两个易于跟踪的事情。据说我们有两个人的信息表,ShoeSize和IQ。你有一些人的ShoeSize信息,一些人的一些智商信息。并且在两个表上都有一个PersonID可以加入。

从右上方顺时针方向(即使这是从一些更复杂和人为的案例开始):

  • Shoe Size RIGHT JOIN IQ - >给我所有的IQ信息。如果我们有这些人,请包括任何鞋码信息。
  • ShoeSize RIGHT JOIN IQ WHERE ShowSize.PersonID = NULL - >给我所有的IQ信息,但仅适用于没有鞋码信息的人
  • ShoeSize FULL OUTER JOIN IQ WHERE ShoeSize.PersonID = NULL AND IQ.PersonID = NULL - >仅为没有IQ信息的人提供鞋码信息,并为没有鞋码信息的人提供IQ信息
  • 鞋子尺寸FULL OUTER JOIN IQ - >给我所有鞋子尺码和所有IQ数据。如果任何Shoe Sizes和IQ记录具有相同的PersonID,请将它们包含在一行中。
  • ShoeSize LEFT JOIN IQ WHERE IQ.PersonID = NULL - >给我所有的鞋号信息,但仅适用于没有IQ信息的人
  • ShoeSize LEFT JOIN IQ - >给我所有鞋码信息。如果我们有这些人,请包括任何IQ信息。
© www.soinside.com 2019 - 2024. All rights reserved.