1. 程式人生 > >帶left join 的sql的執行順序

帶left join 的sql的執行順序

bec serve rom result sdn summary 應用 before BE

顧名思義, 這個概念得名於笛卡兒. 在數學中,兩個集合 X 和 Y 的笛卡兒積(Cartesian product),又稱直積,表示為 X × Y,是其第一個對象是 X 的成員而第二個對象是 Y 的一個成員的所有可能的有序對.

假設集合A={a,b},集合B={0,1,2},則兩個集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)}。可以擴展到多個集合的情況。類似的例子有,如果A表示某學校學生的集合,B表示該學校所有課程的集合,則A與B的笛卡爾積表示所有可能的選課情況。


2.Join類型

cross join 是笛卡兒乘積就是一張表的行數乘以另一張表的行數.
inner join 只返回兩張表連接列的匹配項.
left join 第一張表的連接列在第二張表中沒有匹配是,第二張表中的值返回null.
right join 第二張表的連接列在第一張表中沒有匹配是,第一張表中的值返回null.
full join 返回兩張表中的行 left join+right join.

3.在對兩表進行各種類型的join (cross, left, right, full, inner)時, 都需要構造笛卡爾積.

有時想想不可思議, 若兩個特大表進行join, 難道sql就直接上笛卡爾積嗎? 難道不事前進行on的條件過濾嗎? 那數據量得多大?

4.查一下MSDN就清楚了整個SQL的執行順序.

http://msdn.microsoft.com/en-us/library/ms189499(v=SQL.100).aspx

Processing Order of the SELECT statement
The following steps show the processing order for a SELECT statement.

1.FROM

2.ON

3.JOIN

4.WHERE

5.GROUP BY

6.WITH CUBE or WITH ROLLUP

7.HAVING

8.SELECT

9.DISTINCT

10.ORDER BY

11.TOP

也就是說, 先進行on的過濾, 而後才進行join, 這樣就避免了兩個大表產生全部數據的笛卡爾積的龐大數據.

這些步驟執行時, 每個步驟都會產生一個虛擬表,該虛擬表被用作下一個步驟的輸入。這些虛擬表對調用者(客戶端應用程序或者外部查詢)不可用。只是最後一步生成的表才會返回 給調用者。

如果沒有在查詢中指定某一子句,將跳過相應的步驟。

下面是<<Inside Microsoft SQL Server 2008 T-SQL Querying>>一書中給的一幅SQL 執行順序的插圖.

技術分享圖片

5.On的其余過濾條件放Where裏效率更高還是更低?

select * from table1 as a

inner join table2 as b on a.id=b.id and a.status=1

select * from table1 as a

inner join table2 as b on a.id=b.id

where a.status=1

查查MSDN就清楚了. http://msdn.microsoft.com/en-us/library/ms189499(v=SQL.100).aspx

There can be predicates that involve only one of the joined tables in the ON clause. Such predicates also can be in the WHERE clause in the query. Although the placement of such predicates does not make a difference for INNER joins, they might cause a different result when OUTER joins are involved. This is because the predicates in the ON clause are applied to the table before the join, whereas the WHERE clause is semantically applied to the result of the join.

翻譯之後是, 如果是inner join, 放on和放where產生的結果一樣, 但沒說哪個效率速度更高? 如果有outer join (left or right), 就有區別了, 因為on生效在先, 已經提前過濾了一部分數據, 而where生效在後.

綜合一下, 感覺還是放在on裏更有效率, 因為它先於where執行.

聽說可以通過sql的查詢計劃來判別實際的結果, 明天再研究, 歡迎高手給與批評指正.

********************************************************************************************************

2011/11/21 最新體會

剛看到<<Microsoft SQL Server 2008技術內幕: T-SQL查詢>>一書中對於連接的描述和我先前理解的不太一樣;

Itzib在書上說先笛卡爾積, 然後再on過濾, 如果join是inner的, 就繼續往下走, 如果join 是left join, 就把on過濾掉的左主表中的數據再添加回來; 然後再執行where裏的過濾;

on中不是最終過濾, 因為後面left join還可能添加回來, 而where才是最終過濾.

只有當使用外連接(left, right)時, on 和 where 才有這個區別, 如果用inner join, 在哪裏制定都一樣, 因為on 之後就是where, 中間沒有其它步驟.

帶left join 的sql的執行順序