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 執行順序的插圖.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM