我继承了一个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);
1条答案
按热度按时间xfb7svmp1#
当这些都是
INNER JOIN
时,这个语法有点无意义,如果我是诚实的,但我会在后面讨论这个。让我们来看看你的第一条语句:
我们这里有一个延迟的
ON
子句,用于INNER JOIN
到#TableB
。第二个ON
子句实际上用于#TableB
上的INNER JOIN
。当使用此语法时,不能引用
JOIN
延迟的表范围 * 之外 * 的对象。这不是完全相同的语法(因为它使用派生表),但使用如下查询可能更容易说明第二个查询失败的原因:这将生成类似的错误,因为派生表中无法引用别名为
TableA
的表。在我看来,这种语法在涉及
LEFT JOIN
时更有意义。因此,在这里,
LEFT JOIN
要找到一个相关行,那么TableC
中 * 必须 * 有一个与TableB
相关的行,如果没有找到来自INNER JOIN
的行,那么TableB
也不会被联接。这与下面的查询不同:在这里,这会有效地将
LEFT JOIN
到TableB
转换为隐式INNER JOIN
,因为行 * 需要 * 在TableC
中找到,而找到行的唯一方法是TableB.Id2
具有非NULL
值(如果没有找到行,则不可能找到)。