孔夫子*_*孔夫子 8 mysql postgresql oracle join sql-server
我有一个看起来像这样的查询:
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
Run Code Online (Sandbox Code Playgroud)
将按照什么顺序解析连接?我对 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
Run Code Online (Sandbox Code Playgroud)
从逻辑上讲,连接是按照ON
从左到右的子句顺序解析的。
每个连接的输出是进入下一个连接的虚拟表。
因此,对于您问题中的查询,A LJ B
然后将 的虚拟表结果正确连接到C
. 的连接条件B.Col3 = C.Col4
将丢失原始左连接保留的任何空扩展行,有效地将第一个连接转换回内部连接,然后生成的虚拟表(保留来自 的所有行C
)被内部连接到 上D
。
所以你的初始查询可以简化为
SELECT *
FROM TBLA A
INNER 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
Run Code Online (Sandbox Code Playgroud)
这实际上与 (A IJ B) ROJ (C IJ D)
ON
子句的顺序不一定与表在查询中出现的顺序相同。这也可以改写为(C IJ D) LOJ (A IJ B)
SELECT *
FROM TBLC C
INNER JOIN TBLD D
ON C.Col5 = D.Col6
LEFT JOIN TBLA A
INNER JOIN TBLB B
ON A.Col1 = B.Col2
ON B.Col3 = C.Col4
Run Code Online (Sandbox Code Playgroud)
on 子句的位置意味着外连接是在两个虚拟表之间执行的 (C IJ D)
,(A IJ B)
而不仅仅是单个表。
在您的第二个查询概念上,虚拟表A x C
左连接到 B 保留整个笛卡尔积,然后将结果D
与谓词连接C.Col5 = D.Col6
。不内在这消除了从最终结果没有任何行会合之间C
和D
这意味着它等同于
SELECT *
FROM TBLC C
JOIN TBLD D
ON C.Col5 = D.Col6
CROSS JOIN TBLA A
LEFT JOIN TBLB B
ON A.Col1 = B.Col2
AND B.Col3 = C.Col4
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2995 次 |
最近记录: |