多个左连接 - 啥是“左”表?
Posted
技术标签:
【中文标题】多个左连接 - 啥是“左”表?【英文标题】:Multiple LEFT JOINs - what is the "left" table?多个左连接 - 什么是“左”表? 【发布时间】:2016-07-08 05:18:51 【问题描述】:我已经使用它年了,所以现在是完全理解它的时候了。假设这样的查询:
SELECT
*
FROM a
LEFT JOIN b ON foo...
LEFT JOIN c ON bar...
documentation 告诉我们
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
? (或者,是一样的吗?)
【问题讨论】:
两者都是,这取决于您如何连接数据(示例中的 foo 和 bar。例如,如果在语句“... JOIN c ON bar...”中,条件使用表 a 和 b,它将是 JOIN b ON foo。(a left join b) left join c
,即第一个a
是左表,然后(a left join b)
是下一个左表。
@jarlh 如果您将此作为答案并提供参考,我会接受。
考虑一下如果你的陈述都在一行上会是什么样子(不利于可读性,但只是为了理解这种情况)。当您使用 LEFT [OUTER] JOIN
时,您要求它将表上的 all 行保留在此语句的 left ( a
),无论指定的下一个表 (b
) 中是否有任何行与您的布尔表达式匹配。
【参考方案1】:
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
部分下的documentation 中有解释:
如有必要,请使用括号来确定嵌套顺序。在里面 没有括号,
JOIN
s 从左到右嵌套。无论如何JOIN
比分隔FROM
-list 项的逗号更紧密地绑定。
因此,一系列LEFT JOIN
s 将所有记录保留在第一个提到的表中。这是一种方便。
请注意,FROM
子句的解析是相同的,与连接类型无关。
【讨论】:
我已经调整了您示例的缩进,以更加强调括号。如果您不同意这看起来更好,请随时向我道歉。 :) @IMSoP 。 . .我非常不同意它效果更好,但我不会改变它。【参考方案2】:可能两者都有,具体取决于您加入数据的方式(示例中的 foo 和 bar)。
例如,如果在您的示例中,您想将 a 与 b 连接,a 与 c 连接,则 T1 将是 a。
但是,如果您的意图是将 a 与 b 连接起来,并将结果与 c 连接起来,那么 T1 将是 LEFT JOIN b ON foo。
在最后一种情况下,如果你这样写,将会提高可读性:
(a LEFT JOIN b ON foo) LEFT JOIN c ON bar
【讨论】:
【参考方案3】:这里是多重连接操作。 SQL 是一种语言,您可以在其中描述要获得的结果,而不是如何获得结果。优化器将决定首先执行哪个连接,这取决于它认为最有效的方式。 你可以在这里阅读一些信息 https://community.oracle.com/thread/2428634?tstart=0 我认为,它对 PostgreSQL 也是一样的
【讨论】:
您能提供一些参考吗? @Gleboss 。 . .语义顺序(如何解释连接)与执行顺序(如何实现连接)无关。因此,您回答了一个不同的问题。以上是关于多个左连接 - 啥是“左”表?的主要内容,如果未能解决你的问题,请参考以下文章