SQL中把筛选条件放在left outer join的on 和 where 后面的区别

SQL中把筛选条件放在left outer join的on 和 where 后面的区别

create table [Table_1](
[PKey] int
,[FKey] int
,[value1] int
,[value2] int
)
create table[Table_2]
([PKey] int
,[value1] int
,[value2] int
)
drop table [Table_1]
drop table [Table_2]
delete[Table_1]
delete[Table_2]
insert into [Table_1] values(1,0,21,31)
insert into [Table_1] values(2,0,22,31)
insert into [Table_1] values(3,0,23,31)
insert into [Table_1] values(4,0,24,31)
insert into [Table_1] values(5,0,21,31) --duplicate 21
insert into [Table_1] values(6,0,25,31) --no 25 in table2
insert into [Table_1] values(5,1,21,31) --condition table1 fkey =1

insert into [Table_2] values(6,21,32)
insert into [Table_2] values(7,22,32)
insert into [Table_2] values(8,23,33) -- for seeing on and where difference
insert into [Table_2] values(9,24,32)
insert into [Table_2] values(10,26,32) -- no 26 in table1
select * from [Table_1]
select * from [Table_2]
----select t1.*,'|' n,t2.* from Table_1 t1
----inner join Table_2 t2 on t1.value1 =t2.value1
--left outer join learning
select t1.*,'|' n,t2.* from Table_1 t1
left outer join Table_2 t2 on t1.value1 =t2.value1 order by t1.value1
--part1:
select t1.*,'|' n,t2.* from Table_2 t2
left outer join Table_1 t1 on t1.value1 =t2.value1
order by t1.value1

--part2:

select t1.*,'|' n,t2.* from Table_2 t2
left outer join Table_1 t1 on t1.value1 =t2.value1
where t1.fkey = 0
order by t1.value1

--part3:

select t1.*,'|' n,t2.* from Table_2 t2
left outer join Table_1 t1 on t1.fkey = 0
and t1.value1 =t2.value1
order by t1.value1

left join result:

 

自己的理解:

part1 vs part2:join之后,对结果集进行 where筛选,所以最终结果不会有 t1.fkey = 0的行。

part1 vs part3:join时,对table_1进行 t1.fkey = 0筛选得到虚拟table_1_2,然后table_1_2与table2进行join。

基于理论:

T-SQL在查询各个阶级分别干了什么:

(1)FROM 阶段

    FROM阶段标识出查询的来源表,并处理表运算符。在涉及到联接运算的查询中(各种join),主要有以下几个步骤:

  a.求笛卡尔积。不论是什么类型的联接运算,首先都是执行交叉连接(cross join),求笛卡儿积,生成虚拟表VT1-J1。

      b.ON筛选器。这个阶段对上个步骤生成的VT1-J1进行筛选,根据ON子句中出现的谓词进行筛选,让谓词取值为true的行通过了考验,插入到VT1-J2。

      c.添加外部行。如果指定了outer join,还需要将VT1-J2中没有找到匹配的行,作为外部行添加到VT1-J2中,生成VT1-J3。

    经过以上步骤,FROM阶段就完成了。概括地讲,FROM阶段就是进行预处理的,根据提供的运算符对语句中提到的各个表进行处理(除了join,还有apply,pivot,unpivot)

(2)WHERE阶段

     WHERE阶段是根据<where_predicate>中条件对VT1中的行进行筛选,让条件成立的行才会插入到VT2中。

(3)GROUP BY阶段

      GROUP阶段按照指定的列名列表,将VT2中的行进行分组,生成VT3。最后每个分组只有一行。

(4)HAVING阶段

      该阶段根据HAVING子句中出现的谓词对VT3的分组进行筛选,并将符合条件的组插入到VT4中。

(5)SELECT阶段

  这个阶段是投影的过程,处理SELECT子句提到的元素,产生VT5。这个步骤一般按下列顺序进行

        a.计算SELECT列表中的表达式,生成VT5-1。

        b.若有DISTINCT,则删除VT5-1中的重复行,生成VT5-2

        c.若有TOP,则根据ORDER BY子句定义的逻辑顺序,从VT5-2中选择签名指定数量或者百分比的行,生成VT5-3

(6)ORDER BY阶段

     根据ORDER BY子句中指定的列明列表,对VT5-3中的行,进行排序,生成游标VC6. 

copy一张别人转发的图。下面是<<Inside Microsoft SQL Server 2008 T-SQL Querying>>一书中给的一幅SQL 执行顺序的插图.

原文地址:https://www.cnblogs.com/watermarks/p/5416835.html