使用 APPLY
APPLY 運算符的左操作數和右操作數都是表表達式。這些操作數之間的主要區別是,right_table_source 可以使用表值函數,從 left_table_source 獲取一個列作爲函數的參數之一。left_table_source 可以包括表值函數,但不能以來自 right_table_source 的列作爲參數。
APPLY 運算符通過以下方式工作,以便爲 FROM 子句生成表源:
- 對 left_table_source 的每行計算 right_table_source 的值來生成行集。
right_table_source 中的值依賴於 left_table_source。right_table_source 可以按以下方式近似表示:TVF(left_table_source.row)
,其中,TVF
是表值函數。 - 通過執行 UNION ALL 操作,將計算 right_table_source 的值時爲每行生成的結果集與 left_table_source 組合起來。
APPLY 運算符的結果生成的列的列表是來自 left_table_source(與來自 right_table_source 的列的列表相組合)的一組列。
演示一下APPLY 運算符的用法:
--建一個表
--插入測試數據
INSERT INTO MyData VALUES('') INSERT INTO MyData VALUES('a,b,c') INSERT INTO MyData VALUES('q') INSERT INTO MyData VALUES('i,p') GO select * from MyData go |
--查詢結果
ids Data 1 2 a,b,c 3 q 4 i,p |
建立一個表,作用是:按逗號分解字符,分解出的每一個字符做一行數據返回
create FUNCTION fun_MyData( @data AS NVARCHAR(1000) ) RETURNS @tem TABLE( id INT , value nvarchar(100) ) AS BEGIN select @data=isnull(@data,'') if len(@data)=0 return --字符長度爲0 ,退出 declare @id AS INT select @id=1 declare @end AS INT select @end = CHARINDEX(',', @data) while(@end>0) begin insert into @tem(id,value) select @id,left(@data,@end-1) select @id=@id+1 select @data=right(@data,len(@data)-@end) select @end = CHARINDEX(',', @data) end if len(@data)>0 begin insert into @tem(id,value) select @id,@data end RETURN END |
SELECT m.ids, f.*
FROM MyData m CROSS APPLY fun_MyData(data) f
go
--結果
ids id value
2 1 a
2 2 b
2 3 c
3 1 q
4 1 i
4 2 p
SELECT m.ids, f.* FROM MyData m OUTER APPLY fun_MyData(data) f g o |
--結果
ids id value
1 NULL NULL
2 1 a
2 2 b
2 3 c
3 1 q
4 1 i
4 2 p
我們看到OUTER APPLY返回的結果行比CROSS APPLY多。
這一點有點象inner join(內部聯接)和Left Outer Join(左外部聯接)之間的關係.
其實APPLY有兩種形式:CROSS APPLY 和 OUTER APPLY。
CROSS APPLY僅返回外部表中通過表值函數生成結果集的行。
OUTER APPLY既返回生成結果集的行,也返回不生成結果集的行,其中表值函數生成的列中的值爲 NULL。