T-SQL中的APPLY用法
原文出處:http://www.sqlservercentral.com/articles/Stairway+Series/121318/
從SQL Server 2005開始,微軟添加了一個新的運算子用於關聯一個帶有函式的結果集,並把函式應用於表/檢視中的每一個限定行中。這個運算子就是APPLY。從技術上來說,這個操作的底層邏輯並不是實際的“JOIN”,但由於它的用法更像是JOIN,所以通常會與關聯操作相關聯。APPLY操作分為兩種格式:CROSS APPLY或OUTER APPLY。在本文中會分別展示這兩種格式。
APPLY 簡介:
你是否曾經寫過SELECT語句去呼叫一個表值函式或把表值表示式的每一個記錄與表匹配?如果有過這樣的經歷,APPLY運算子會幫到你。APPLY分為CROSS APPLY和OUTER APPLY。
第一種格式叫CROSS APPLY。它從CROSSAPPLY的一邊提取表或資料集的每行的所需列值,然後作為輸入值傳輸到另外一邊的表值函式或表示式中。然後把所有關聯的值使用UNION ALL運算符合並。如果表值函式針對輸入資料沒有滿足呼叫條件時,函式將不返回輸出,並且這部分的表或結果集將不會出現在最終結果中,因為它不能與表值函式的資料關聯。
第二種格式叫OUTER APPLY。其行為和CROSSAPPLY類似,但返回不能呼叫表值函式/表示式的值。
為了更好理解這兩種格式,下面來演示一下:
測試資料和函式:
USE tempdb; GO IF object_id('dbo.Product') IS NOT NULL DROP TABLE dbo.Product; IF object_id('dbo.SearchString') IS NOT NULL DROP TABLE dbo.SearchString; IF object_id('dbo.FindProductLike') IS NOT NULL DROP FUNCTION dbo.FindProductLike; CREATE TABLE dbo.Product ( ID INT IDENTITY , ProductNameVARCHAR(100) , Price MONEY ); INSERT INTOdbo.Product VALUES ( 'Red SantaSuit', 199.99 ), ( 'Candy Canes', 1.99 ), ( 'Fake Snow', 2.99 ), ( 'Red Bells', 49.99 ), ( 'LED Lights', 6.99 ); CREATE TABLE dbo.SearchString ( ID INT IDENTITY , String VARCHAR(100) ); INSERT INTO dbo.SearchString VALUES ( 'Red' ), ( 'Lights' ), ( 'Star' ); GO CREATE FUNCTION dbo.FindProductLike ( @FindString VARCHAR(100) ) RETURNS TABLE AS RETURN ( SELECT ProductName, Price FROM dbo.Product WHERE ProductName LIKE '%' + @FindString + '%' )
建立表和表值函式
上面的指令碼中建立了一個叫做Product的表,包含了5個不同的產品。同時也建立了一個叫做SearchString的表,包含了3個不同的字串。最後建立一個叫做FindProductLike的表值函式。該函式接收一個@FindString引數,並在Product表中找出所有包含@FindString的ProductName。
使用CROSS APPLY 運算子:
CROSS APPLY會對相關聯的每一行都應用該函式
USE tempdb; GO SELECT * FROM dbo.SearchString AS S CROSS APPLYdbo.FindProductLike(S.String);
結果如下:
回看程式碼可以看到,程式碼中使用CROSSAPPLY關聯SearchString表中的結果集和FindProductLike表值函式。CROSS APPLY從SearchString中獲取String值,然後呼叫函式FindProductLike。如果函式返回資料,則與SearchString的行關聯。
前兩行的資料來自於字串“Red”,當“Red”傳輸給函式後,返回包含該值的ProductName和Price,然後和SearchString關聯,把包含“Red”值的產品返回到結果集中。第三行資料和前兩行的產生原理一致,但是是由“Lights”產生。字串“Star”由於沒有在Product中得到匹配值,所以不返回結果。
使用OUTER APPLY 運算子:
該操作符和CROSS APPLY的唯一區別是返回所有資料,包括沒有匹配的值:
USE tempdb; GO SELECT * FROM dbo.SearchString AS S OUTER APPLYdbo.FindProductLike(S.String);
從結果中可以看出,對於字串“Star”,OUTER APPLY也返回結果,只是返回NULL。
使用表值表示式:
下面演示一下使用表值表示式與APPLY的操作。
USE tempdb; GO SELECT * FROM dbo.SearchString as S CROSS APPLY (SELECT ProductName, Price FROM dbo.Product WHERE ProductName like '%' + S.String + '%') as X
從結果上來看,和CROSS APPLY無異,僅僅是把表值函式換成了表值表示式。
總結:
APPLY運算可以把資料集中的資料與表值函式或表值表示式關聯,使用APPLY可以針對表值函式或表示式的資料集進行基於集合的查詢。在這種情況下可以考慮使用APPLY運算子。