我知道这是一个基本问题,但同样为什么我很难理解这种情况。假设我们有3个表(A,B,C),它们都具有1-1关系。但是表B并不包含表A包含的所有值。因此,它们之间必须保持左连接。那么,为什么下面的代码将所有联接变成一个内部联接,而唯一的内部联接却不仅仅在B和C表之间起作用?你能给我解释一下吗?
SELECT A.*
FROM A
LEFT OUTER JOIN B ON B.ID = A.ID
INNER JOIN C ON C.ID = B.ID
这个问题不是关于外部联接或内部联接可以或不能使用表中的值的问题。关于它们一起使用时,sql引擎如何在它们上工作?也许这里的执行顺序是什么?这就是我试图理解的。谢谢。
答案 0 :(得分:1)
这里的问题与理解JOIN
的处理顺序有关。
首先执行LEFT OUTER JOIN
,并将按预期返回A
的所有结果,以及B
的那些匹配结果(如果连接失败,则返回NULL
的值)。
此后,然后针对第一个INNER JOIN
的合并结果执行C
至LEFT OUTER JOIN
。由于没有匹配项将B
到C
的不存在的匹配项加入进来,因此将这些结果从结果中排除 ,为您提供缩减的结果。
迎合这种情况的典型方法是使用第二个LEFT OUTER JOIN
代替INNER JOIN
:
SELECT *
FROM A
LEFT OUTER JOIN B ON B.ID = A.ID
LEFT OUTER JOIN C ON C.ID = B.ID
这仍将返回A
中的所有内容,并且仅返回B
和C
中的匹配记录。
如果打算仅在B
中返回 结果,而在C
中具有相应的条目,则可以将查询的工作方式修改为类似未测试 SQL:
SELECT *
FROM A
LEFT OUTER JOIN (
SELECT B.ID
FROM B
INNER JOIN C ON C.ID = B.ID
) btmp ON btmp.ID = A.ID
这只会返回B
中与C
中的行匹配的结果,然后将它们加入A
。
答案 1 :(得分:1)
A left outer join B
意味着从A返回所有内容,即使B中没有匹配的内容,对吗?
因此,您将从A中获得每一行,其中NULL
代表B中没有对应关系的行,而值与那些在B中具有匹配项的行对应。
然后将此集合(inner joined)
与C相连。这意味着(A left join B) and C
之间只有匹配的那些,并且连接条件位于column of B
=>上,而实际上有一个匹配的首先显示A的值。其他的是NULL
。
此article是SQL中联接的出色视觉说明。
答案 2 :(得分:1)
简单地说,如果在表B中找不到匹配项,则此:
INNER JOIN C ON C.ID = B.ID
表示:
INNER JOIN C ON C.ID = NULL
连接条件失败。
您可以添加括号以获得预期结果:
SELECT A.*
FROM A
LEFT OUTER JOIN (B INNER JOIN C ON B.ID = C.ID) ON A.ID = B.ID
答案 3 :(得分:0)
比较这两个查询(第一个查询可能看起来不正确,但这是正确的!)
SELECT A.* FROM A
LEFT OUTER JOIN B
INNER JOIN C ON C.ID = B.ID
ON B.ID = A.ID
vs
SELECT * FROM A
LEFT OUTER JOIN B ON B.ID = A.ID
INNER JOIN C ON C.ID = B.ID
在第二个查询中,您询问: 不要将b加入a 并将c与上一步的结果进行内部联接。
最后一个内部联接将忽略所有空记录
但是第一个查询是不同的 问: 将C内部连接到B,然后将结果左连接到A
在这种情况下,来自A的所有与内部联接结果不对应的记录都将包含在结果中。