我有一个看起来像这样的查询:
SELECT *
FROM TBLA A
LEFT JOIN TBLB B ON A.Col1 = B.Col2
RIGHT JOIN TBLC C ON B.Col3 = C.Col4
JOIN TBLD D ON C.Col5 = D.Col6
连接将按什么顺序解决?我对 SQL Server 最感兴趣,并将对它的解释标记为答案,但对 ANSI/ISO 标准以及它在各种 RDBMS 中的工作方式同样感兴趣。
这个问题的原因是要弄清楚为什么结果与这个查询不同
SELECT *
FROM TBLA A
CROSS JOIN TBLC C
LEFT JOIN TBLB B ON A.Col1 = B.Col2 AND B.Col3 = C.Col4
JOIN TBLD D ON C.Col5 = D.Col6
从逻辑上讲
ON
,连接是按照从左到右的子句顺序解决的。每个连接的输出是一个进入下一个连接的虚拟表。
因此,对于您的问题中的查询,虚拟表结果
A LJ B
将正确连接到C
. 的连接条件B.Col3 = C.Col4
将丢失由原始左连接保留的任何空扩展行,有效地将第一个连接转换回内连接,然后将生成的虚拟表(保留来自 的所有行C
)内连接到D
。所以你的初始查询可以简化为
这实际上与
(A IJ B) ROJ (C IJ D)
子句的顺序
ON
不一定与表在查询中出现的顺序相同。这也可以重写为(C IJ D) LOJ (A IJ B)
on 子句的位置意味着外连接是在两个虚拟表之间执行的,而这两个虚拟表是由单个表产生的
(C IJ D)
,(A IJ B)
而不仅仅是在单个表上。从概念上讲,在您的第二个查询中,虚拟表
A x C
与 B 保持连接,保留整个笛卡尔积,然后将其结果D
与 predicate连接C.Col5 = D.Col6
。这消除了最终结果中没有内部连接的任何行,这C
意味着D
它相当于在 PostgreSQL 中:
http://www.postgresql.org/docs/9.1/static/sql-select.html#SQL-FROM