多个LEFT JOIN - "left" 表是什么?

17

我使用这个已经多年了,所以现在是时候完全理解它了。比方说一个像这样的查询:

SELECT 
  *
FROM a
LEFT JOIN b ON foo...
LEFT JOIN c ON bar...

文档告诉我们:

T1 { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2 ON boolean_expression

LEFT OUTER JOIN

首先执行内部连接。 然后,对于T1中任何一行与T2中的任何行都不满足连接条件的情况,将添加一个具有T2列中的空值的连接行。 因此,连接表始终至少有每个T1行的一行。

问题很简单:在这种情况下,T1是什么? 是a吗? 还是a LEFT JOIN b ON foo?(或者是一样的吗?)


1
这取决于您如何连接数据(例如在您的示例中的foo和bars)。例如,在语句“... JOIN c ON bar...”中,如果条件使用表a和b,则为JOIN b ON foo。 - Walter_Ritzel
2
(a left join b) left join c,即首先将 a 作为左表,然后将 (a left join b) 作为下一个左表。 - jarlh
@jarlh 如果您将此内容编写为答案并提供参考资料,我会接受它。 - vektor
考虑一下如果您的语句全部在一行上会是什么样子(这不利于可读性,但只是为了理解这种情况)。当您使用 LEFT [OUTER] JOIN 时,您要求它保留此语句 (a) 左侧表格中的所有行,而不管下一个指定的表格 (b) 中是否有任何与您的布尔表达式匹配的行。 - CactusCake
3个回答

11

FROM子句从左到右解析条件(除非由括号覆盖)。所以:

FROM a 
LEFT JOIN b
     ON foo... 
LEFT JOIN c
     ON bar...

被解析为:

FROM (
        a 
        LEFT JOIN b
           ON foo...
     ) 
LEFT JOIN c
     ON bar...

这在文档FROM子句的join-type部分有解释:

如果需要确定嵌套的顺序,请使用括号。没有括号时,JOIN从左到右嵌套。无论如何,JOIN的优先级都比分隔FROM列表项的逗号更高。

因此,一系列LEFT JOIN保留了在第一个表中提到的所有记录。 这是很方便的。

请注意,不管连接类型如何,FROM子句的解析都是相同的。


我已经微调了您的示例缩进,以更加强调括号。如果您不同意这样看起来更好,请随时恢复并接受我的道歉。 :) - IMSoP
@IMSoP...我非常不同意它的效果更好,但我不会改变它。 - Gordon Linoff

0

这取决于你如何连接数据(例如你的示例中的foo和bar)。

例如,如果在你的示例中,你想要将a与b和a与c连接,那么T1将是a。

但是,如果你的意图是将a与b连接并将结果与c连接,则T1将是LEFT JOIN b ON foo的a。

在最后一种情况下,如果你这样写,可读性会有所提高:

(a LEFT JOIN b ON foo) LEFT JOIN c ON bar

0
这里有多个连接操作。 SQL是一种语言,你描述要得到的结果,而不是如何得到它们。优化器将根据其认为最有效的方式决定首先执行哪个连接。 您可以在此处阅读一些信息
https://community.oracle.com/thread/2428634?tstart=0
我认为,PostgreSQL也是同样的工作方式。

你能提供一些参考资料吗? - vektor
@Gleboss……语义顺序(连接的解释方式)与执行顺序(连接的实现方式)无关。因此,你回答了一个不同的问题。 - Gordon Linoff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接