關於Cross Join 和 Outer/Cross Apply
2013-11-23 10:22
316 查看
先為大家準備點數據:
的結果是一樣的:
結果是:
是不是覺得很眼熟,是的,上面的語句和
select *
from TA a
inner join TBb
on a.Acol
= b.Bcol1
是一樣的,甚至執行計畫都是一樣的,上面的語句完全按照inner join的思路去執行。
再看用outer apply:
結果是:
是不是依然很眼熟,沒錯,它和
select*
from TA
a left join
TBb ona.ACol=
b.BCol1
是一樣的。執行計畫依然一樣,上面的語句按left join的思路去執行。
既然這樣,為什麼還要多出一個Cross/Outer Apply呢?
假設現在有一個需求,將tmp中每一行都以@@作為分隔符拆分為列表,然後與拆分前的那一行作交叉聯接(笛卡爾積)。
拆分函數網上有很多,為了節省篇幅就不放代碼了,可以到我另一篇博文中看。假設此拆分函數為dbo.f_Split(@str varchar(1000),@delimiter
varchar(100) = '' ),@str為源字符串,@delimiter為分隔符。先用常量作為函數參數來理解一下上面所說的需求:
結果:
可以看到TA中的行和表值函數返回的表作了聯接。上面的cross join就可以做到。再看一下用表中的列作函數參數:
結果是報錯:
現在Cross Apply
的作用就真正體現出來了:
結果:
2) 在不涉及到表值函數的情況下,Cross Apply 和 Outer Apply所起的作用與Inner
Join 和 Left Join 一樣,所以一般情況下不要用Apply,這樣反而容易造成不易理解的負面效應;
3) Cross / Outer Apply可以說完全為表值函數而生,支持了表的每一行和由此行中數據作爲參數去調用表值函數而返回的結果表作交叉連接(類笛卡爾積)。看MSDN的介紹Apply的文檔,沒有一個實例沒有用到表值函數(TF)的。
CREATE TABLE TA(Acol INT); GO INSERT INTO TA SELECT 1 UNION ALL SELECT 2; GO CREATE TABLE TB(Bcol1 INT,Bcol2 VARCHAR(10)); GO INSERT INTO TB SELECT -1, 'a' UNION ALL SELECT 1, 'b' UNION ALL SELECT 3, 'c'; GO
1. Cross Join
Cross Join ,交叉聯接,其實就是笛卡爾積。select * from TA cross join TB 或 select * from TA,TB
的結果是一樣的:
2. Cross / Outer Apply
請看下面這條語句:select * from TA a cross apply (select * from TB where Bcol1=a.Acol) b
結果是:
是不是覺得很眼熟,是的,上面的語句和
select *
from TA a
inner join TBb
on a.Acol
= b.Bcol1
是一樣的,甚至執行計畫都是一樣的,上面的語句完全按照inner join的思路去執行。
再看用outer apply:
select * from TA a outer apply (select * from TB where Bcol1=a.Acol) b
結果是:
是不是依然很眼熟,沒錯,它和
select*
from TA
a left join
TBb ona.ACol=
b.BCol1
是一樣的。執行計畫依然一樣,上面的語句按left join的思路去執行。
既然這樣,為什麼還要多出一個Cross/Outer Apply呢?
3. Cross / Outer Apply的專屬功能
測試數據:CREATE TABLE tmp([str] VARCHAR(100)) GO INSERT INTO tmp SELECT 'I@@Love@@Coding' UNION ALL SELECT 'This@@is@@it' GO
假設現在有一個需求,將tmp中每一行都以@@作為分隔符拆分為列表,然後與拆分前的那一行作交叉聯接(笛卡爾積)。
拆分函數網上有很多,為了節省篇幅就不放代碼了,可以到我另一篇博文中看。假設此拆分函數為dbo.f_Split(@str varchar(1000),@delimiter
varchar(100) = '' ),@str為源字符串,@delimiter為分隔符。先用常量作為函數參數來理解一下上面所說的需求:
select * from TA cross join dbo.f_Split('Xiao;;Ming',';;') 或 select * from TA,dbo.f_Split('Xiao;;Ming',';;')
結果:
可以看到TA中的行和表值函數返回的表作了聯接。上面的cross join就可以做到。再看一下用表中的列作函數參數:
select * from tmp a cross Join dbo.f_Split(a.[str],'@@')b
結果是報錯:
現在Cross Apply
的作用就真正體現出來了:
select * from tmp a cross apply dbo.f_Split(a.[str],'@@') b
結果:
4. 小結
1) Cross Join就是笛卡爾積;2) 在不涉及到表值函數的情況下,Cross Apply 和 Outer Apply所起的作用與Inner
Join 和 Left Join 一樣,所以一般情況下不要用Apply,這樣反而容易造成不易理解的負面效應;
3) Cross / Outer Apply可以說完全為表值函數而生,支持了表的每一行和由此行中數據作爲參數去調用表值函數而返回的結果表作交叉連接(類笛卡爾積)。看MSDN的介紹Apply的文檔,沒有一個實例沒有用到表值函數(TF)的。
相关文章推荐
- 初识cross apply & outer apply
- Sql Server cross/outer apply 用法
- sql-(Cross||Outer)Apply
- SQL语句 - MERGE INTO 、Cross/Outer Apply用法理解
- SQL Server CROSS APPLY and OUTER APPLY
- 容易遗忘的一些小代码之 Cross apply and Outer apply
- sql server cross/outer apply 用法
- cross apply / outer apply
- SQL Server 2005 中 Cross join & Cross Apply & Outer Apply 的区别
- sql server cross/outer apply 用法
- CROSS APPLY vs OUTER APPLY
- 【转载】cross apply & outer apply
- 表连接查询INNER JOIN/OUTER JOIN/CROSS JOIN
- SQL中的各种JOIN(inner join,full outer join,left join,right join,cross join )
- simple =, join,left out join,right outer join, cross join
- Linq表连接大全(INNER JOIN、LEFT OUTER JOIN、RIGHT OUTER JOIN、FULL OUTER JOIN、CROSS JOIN)
- spring data jpa将@ManyToOne查询从cross join变成left outer join
- SQL中的JOIN类型解释(CROSS, INNER,OUTER),关键字ON,USING
- inner join,full outer join,left join,right join,cross join
- SQL Server outer apply 和 cross apply