多个左连接 - 啥是“左”表?

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 行保留在此语句的 lefta),无论指定的下一个表 (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 中有解释:

如有必要,请使用括号来确定嵌套顺序。在里面 没有括号,JOINs 从左到右嵌套。无论如何JOIN 比分隔 FROM-list 项的逗号更紧密地绑定。

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

请注意,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 。 . .语义顺序(如何解释连接)与执行顺序(如何实现连接)无关。因此,您回答了一个不同的问题。

以上是关于多个左连接 - 啥是“左”表?的主要内容,如果未能解决你的问题,请参考以下文章

MSSQL:左连接三个表中的多个列

SQL:具有相似表的多个左连接

SQL 左连接与 FROM 行上的多个表?

SQL 左连接与 FROM 行上的多个表?

允许同一个表的多个左外连接?

显示具有多个需要累积的值的左连接