我有以下格式的查询
select
*
from
Table1 t1
inner join Table2 t2
inner join Table3 t3 on t2.ID = t3.ID
on t3.ID = t1.ID
我所知道的:
on
条件会导致错误。 on t2.ID = t3.ID
更改为on t1.ID = t2.ID
会导致错误t1.ID could not be bound
。显然,上述例子是任意的,实际上可能不会产生实际有用的结果。但是,对后来提供on
的内容的解释实际上是很好的。
由于
修改 我不是试图将问题改为有效的东西,而是在我提供它时理解MSSQL正在做什么。
答案 0 :(得分:5)
这种编写连接子句的方法是在SQL Server中生成浓密查询计划的一种方法。查询优化器通常只考虑连接的一侧是基础对象(例如表或索引视图)的连接。
要创建一个计划,其中一个连接的结果直接连接到另一个连接的结果(一个浓密的计划),我们需要使用FORCE ORDER
提示,并使用问题中显示的语法,或使用子查询(或公用表表达式)的等效结构:
-- Four sample tables
DECLARE @T1 TABLE (ID INT PRIMARY KEY);
DECLARE @T2 TABLE (ID INT PRIMARY KEY);
DECLARE @T3 TABLE (ID INT PRIMARY KEY);
DECLARE @T4 TABLE (ID INT PRIMARY KEY);
-- Some data
INSERT @T1 VALUES (1),(2),(3),(4),(5),(6);
INSERT @T2 VALUES (1),(2),(3),(4);
INSERT @T3 VALUES (2),(4),(6);
INSERT @T4 VALUES (1),(2),(3);
-- Bushy plan
SELECT *
FROM @T1
JOIN @T2
ON [@T2].ID = [@T1].ID
JOIN @T3
JOIN @T4
ON [@T4].ID = [@T3].ID
ON [@T4].ID = [@T2].ID
OPTION (FORCE ORDER);
-- Bushy plan, but note column aliases needed
SELECT *
FROM (
SELECT *
FROM @T1 AS T1
JOIN @T2 AS T2
ON T2.ID = T1.ID
) AS Q1 (ID, ID2)
JOIN (
SELECT *
FROM @T3 AS T3
JOIN @T4 AS T4
ON T4.ID = T3.ID
) AS Q2 (ID3, ID4)
ON Q2.ID4 = Q1.ID2
OPTION (FORCE ORDER);
在'怪异'语法中,连接嵌套和ON
clases不需要......但它确实使TSQL难以阅读,至少在我看来。在极少数情况下,一个浓密的计划总是产生比任何左深或右深的查询树更优化的计划,我可能会使用后一种语法。
答案 1 :(得分:3)
您可以使用您指定的格式(假设表格别名正确), if 使用括号。
Select ... -- never use Select *
From (Table1 As T1
Join Table2 As T2
On T2.ID = T1.ID)
Join Table3 As T3
On T3.ID = T1.ID
然而,对于equi-joins(内连接),它确实没有区别,如果你不使用括号,它会更容易阅读。但是,此格式对外连接非常有用。请看以下两个例子:
示例1
Select ...
From Table1 As T1
Left Join Table2 As T2
On T2.T1_ID = T1.ID
Join Table3 As T3
On T3.T2_ID = T2.ID
示例2
Select ...
From Table1 As T1
Left Join (Table2 As T2
Join Table3 As T3
On T3.T2_ID = T2.ID)
On T2.T1_ID = T1.ID
假设在这种情况下,T3.T2_ID
是Table2的不可为空的外键。在Example1中,Inner Join to Table3将有效地过滤掉本来为null的行,因为Table1中不存在给定的T2.T2_ID
。但是,在第二个示例中,Table2和Table3之间的连接是在处理之前的左连接之前完成的。因此,我们将从Table1和Table2获得相同的行:
示例3
Select ...
From Table1 As T1
Left Join Table2 As T2
On T2.T1_ID = T1.ID
答案 2 :(得分:2)
假设你的意思是t1而不是t,那么你的查询是:
select
*
from
Table1 t1
inner join Table2 t2
inner join Table3 t3 on t2.ID = t3.ID
on t3.ID = t1.ID
...可以通过添加它不需要的括号来更清晰:
select
*
from
Table1 t1
inner join
(Table2 t2 inner join Table3 t3 on t2.ID = t3.ID) on t3.ID = t1.ID
实际上,你明确地说“将t2加入t3,然后将t1加入到那里。”
这有帮助吗?
答案 3 :(得分:0)
首先关闭 - 你没有定义什么是
表1是别名t1 表2是别名t2 表3是别名t3
但没有简单的说明。
其次,你没有进行t1到t2的连接,而是从t1到t3,然后是t3到t2。那可行。如果t1和t2之间存在关系(t1.ID = t2.ID),那么“on”语句应直接跟随t2的内连接语句:
select
*
from
Table1 t1
inner join Table3 t3 on t1.ID = t3.ID
inner join Table2 t2 on t3.ID = t2.ID
更新(基于您的更新) t1.ID,t2.ID和t3.ID是否都是相同的数据类型?