Pan*_*tea 6 query t-sql sql-server-2016
我知道执行 SQL 查询的逻辑顺序是:
FROM
ON
JOIN
WHERE
GROUP BY
WITH CUBE or WITH ROLLUP
HAVING
SELECT
DISTINCT
ORDER BY
TOP
Run Code Online (Sandbox Code Playgroud)
如果查询中有多个连接会发生什么,例如,如果我们有这样的查询:
SELECT *
FROM user_branch T1
INNER JOIN dimcustomer2 T2
ON T1.BRANCH_CODE = T2.BRANCH_CODE
INNER JOIN customer_guarantee T3
ON T3.CUSTOMER_NUM = T2.CUSTOMER_NUM
Run Code Online (Sandbox Code Playgroud)
一些示例数据:
customer_guarantee: CUSTOMER_NUM BRANCH_CODE
-------------------------------
A X
B X
C Y
D Z
user_branch: USER_ID BRANCH_CODE
--------------------------------
U1 Y
dimcustomer2: CUSTOMER_NUM BRANCH_CODE
--------------------------------
A Y
B Y
C Y
D Z
Run Code Online (Sandbox Code Playgroud)
这将如何执行?哪个连接会先执行?如果查询中有不同类型的连接怎么办?在这种情况下执行连接的顺序是什么?提前致谢。
And*_*y M 11
确定连接逻辑顺序的一种方法是将示例中的第一个内连接替换为左外连接:
SELECT *
FROM user_branch T1
LEFT JOIN dimcustomer2 T2
ON T1.BRANCH_CODE = T2.BRANCH_CODE
INNER JOIN customer_guarantee T3
ON T3.CUSTOMER_NUM = T2.CUSTOMER_NUM
Run Code Online (Sandbox Code Playgroud)
让我们假设 中的某些行在 中T1
没有匹配项T2
。更具体地说,让我们假设这些是三个表:
SELECT *
FROM user_branch T1
LEFT JOIN dimcustomer2 T2
ON T1.BRANCH_CODE = T2.BRANCH_CODE
INNER JOIN customer_guarantee T3
ON T3.CUSTOMER_NUM = T2.CUSTOMER_NUM
Run Code Online (Sandbox Code Playgroud)
这里有两个连接以及它们执行顺序的两种可能性。
如果首先计算左连接,则其结果将在行不匹配的T2
列中为空T1
:
T1.BRANCH_CODE T2.BARNCH_CODE T2.CUSTOMER_NUM -------------- -------------- --------------- 11 11 230 12 12 235 13 (空) (空) 14 (空) (空) 15 15 260
T3
在使用T2
列的条件上使用内部连接进一步连接该结果将消除不匹配 - 因此,相应的T1
行, - 因为空值不能满足连接的等于条件:
T1.BRANCH_CODE T2.BARNCH_CODE T2.CUSTOMER_NUM T3.CUSTOMER_NUM -------------- -------------- --------------- ------- -------- 11 11 230 230 12 12 235 235 15 15 260 260
这样一些T1
行将从最终结果集中排除。
现在,如果先执行内连接,那么它将生成一个结果集,其中包含来自T2
和T3
匹配内连接条件的行:
T2.BARNCH_CODE T2.CUSTOMER_NUM T3.CUSTOMER_NUM --------------- --------------- --------------- 11 230 230 12 235 235 15 260 260
然后将此结果集外连接到T1
,T1
在外侧,您将获得最终结果,其中包含来自T1
与外连接条件匹配的T2
-T3
内连接的所有行:
T1.BRANCH_CODE T2.BARNCH_CODE T2.CUSTOMER_NUM T3.CUSTOMER_NUM -------------- -------------- --------------- ------- -------- 11 11 230 230 12 12 235 235 13 (空) (空) (空) 14 (空) (空) (空) 15 15 260 260
因此,第二种解释意味着所有T1
行都应该出现在结果中。
由于这两种解释给出了如此不同的结果,很明显只有一种解释是正确的。执行查询,您将看到它实际上是第一个。这意味着从逻辑上讲,连接按照它们在FROM
子句中指定的顺序执行。
请注意,上述结论适用于最传统的连接语法,即:
FROM
T1
... JOIN T2 ON ...
... JOIN T3 ON ...
...
Run Code Online (Sandbox Code Playgroud)
您的示例与该模式匹配,因此结论也适用于它。然而,值得一提的是,我们的结论并不适用,或者至少不那么直接。
从语法上讲,可以在另一个连接中指定一个连接,如下所示:
FROM
T1
JOIN
T2
JOIN T3 ON ..
ON ...
Run Code Online (Sandbox Code Playgroud)
在上述情况下,JOIN T2
之前遇到过JOIN T3
。然而,前一个 join 的声明在这一点上并不完整:它的ON
子条款是最后的,并且只在JOIN T3 ON ...
部分之后进行逻辑评估。所以在这种情况下,T2
首先加入到T3
,然后加入的结果加入到T1
。
你仍然可以争辩说我们的结论站在这里,尽管在这种情况下它并不那么明确。我们得出结论,连接是按照它们在子句中指定的顺序进行评估的FROM
。在这个例子中,我们在解析FROM
子句时遇到的第一个连接在第二个连接时尚未完全指定。
在引入显式JOIN
语法之前,连接是这样指定的:
FROM
T1,
T2,
T3
WHERE
<joining conditions, filter conditions>
Run Code Online (Sandbox Code Playgroud)
大多数(如果不是全部)平台(包括 SQL Server)仍然支持这种类型的联接,有时也称为逗号联接。
如果没有连接条件,逗号连接本质上就是交叉连接。连接条件使其成为内部连接。但是,您可以看到,这种情况下的连接条件来自一个完全不同的子句,即WHERE
子句。
现在,SQL Server 允许您在同一FROM
子句中混合使用逗号连接和常规连接。当您混合使用这样的连接时:
FROM
T1,
T2
JOIN T3 ON ... ,
T4 ...
Run Code Online (Sandbox Code Playgroud)
SQL Server 将在将它们全部交叉连接在一起之前独立于其他项目评估每个单独的逗号分隔项。因此,在上述情况下,T2 JOIN T3 ON ...
连接将在其结果交叉连接之前进行评估T1
(通过可能找到该WHERE
子句的任何连接条件进一步过滤)。我们的结论在这里完全不适用。但是,您可以看到在这种情况下使用了非常不同的语法。
我在 Stack Overflow 上的回答中更详细地讨论了混合语法:The multi-part identifier could not be bound。
恐怕“逻辑执行”这个词没有多大意义;根据定义,查询执行是结果集的物理具体化。我认为您所说的“逻辑执行”是查询编译,即分析查询语法和语义并准备查询计划以实现所述语义的阶段。
查询中的联接表1始终从左到右(或从上到下)计算:
select ... from t_a -- evaluated first
join t_b -- evaluated second
on t_a.c1 = t_b.c3
join t_x -- evaluated third
on t_b.c4 = t_x.c5
...
Run Code Online (Sandbox Code Playgroud)
如果您尝试在ON
子句中引用属于稍后包含在评估序列中的表的列,您可以自己验证这一点。这将无法编译:
select ... from t_a
join t_b
on t_a.c1 = t_c.c8 -- t_c is not known yet
join t_c
...
Run Code Online (Sandbox Code Playgroud)
查询被解析后,执行计划可以按照维护查询语义的任何顺序执行连接。正如手册所说,
FROM
关键字后的表源顺序不影响返回的结果集。
这个问答有点相关。
1 - 一个joined_table
子句由两个table_source
s 和它们对应的ON
子句组成。
归档时间: |
|
查看次数: |
3983 次 |
最近记录: |