sql-server 具有奇怪联接顺序的Sql

eanckbw9  于 2022-10-31  发布在  其他
关注(0)|答案(1)|浏览(134)

我继承了一个SQL查询,但我不熟悉它的语法。
它看起来像

SELECT *
FROM #TableA AS TableA
     INNER JOIN #TableB AS TableB
     INNER JOIN #TableC AS TableC
         ON TableC.Id1 = TableB.Id1
         ON TableB.Id2 = TableA.Id2

SQL Server 2019数据库管理系统。
还有其他几个不相关的查询使用相同的语法,所以这肯定是故意的。
我首先想到的可能是,ON子句的顺序并不重要,因为它们都可以被移到WHERE子句中。
但后来我试着

SELECT *
FROM #TableA AS TableA
     INNER JOIN #TableB AS TableB
     INNER JOIN #TableC AS TableC
         ON TableC.Id1 = TableB.Id1
            AND TableC.Id3 = TableA.Id3
         ON TableB.Id2 = TableA.Id2

上面有一个工具提示
未能绑定ウTableA.Id3 Ж。
执行它会导致错误
'Id3'附近有语法错误
有人能解释一下这种语法是如何工作的吗?
以下是设置代码

CREATE TABLE #TableA (Id1 int, Id2 int, Id3 int);
CREATE TABLE #TableB (Id1 int, Id2 int, Id3 int);
CREATE TABLE #TableC (Id1 int, Id2 int, Id3 int);
xfb7svmp

xfb7svmp1#

当这些都是INNER JOIN时,这个语法有点无意义,如果我是诚实的,但我会在后面讨论这个。
让我们来看看你的第一条语句:

SELECT *
FROM #TableA AS TableA
     INNER JOIN #TableB AS TableB
     INNER JOIN #TableC AS TableC
         ON TableC.Id1 = TableB.Id1
         ON TableB.Id2 = TableA.Id2

我们这里有一个延迟的ON子句,用于INNER JOIN#TableB。第二个ON子句实际上用于#TableB上的INNER JOIN
当使用此语法时,不能引用JOIN延迟的表范围 * 之外 * 的对象。这不是完全相同的语法(因为它使用派生表),但使用如下查询可能更容易说明第二个查询失败的原因:

SELECT *
FROM #TableA AS TableA
     CROSS JOIN (SELECT *
                 FROM #TableB AS TableB
                      INNER JOIN #TableC AS TableC ON TableC.Id1 = TableB.Id1
                 WHERE TableB.Id2 = TableA.Id2) BC;

这将生成类似的错误,因为派生表中无法引用别名为TableA的表。
在我看来,这种语法在涉及LEFT JOIN时更有意义。

SELECT *
FROM #TableA TableA
     LEFT JOIN #TableB TableB
                INNER JOIN #TableC TableC ON TableC.Id1 = TableB.Id1
                ON TableB.Id2 = TableA.Id2;

因此,在这里,LEFT JOIN要找到一个相关行,那么TableC中 * 必须 * 有一个与TableB相关的行,如果没有找到来自INNER JOIN的行,那么TableB也不会被联接。这与下面的查询不同:

SELECT *
FROM #TableA TableA
     LEFT JOIN #TableB TableB ON TableB.Id2 = TableA.Id2
     INNER JOIN #TableC TableC ON TableC.Id1 = TableB.Id1;

在这里,这会有效地将LEFT JOINTableB转换为隐式INNER JOIN,因为行 * 需要 * 在TableC中找到,而找到行的唯一方法是TableB.Id2具有非NULL值(如果没有找到行,则不可能找到)。

相关问题