Sql Server中不經常使用的表運算符之APPLY(2)

Sql Server中不經常使用的表運算符之APPLY(1)中提到,SQL2005中新支持的APPLY的特性:
1.能夠直接將表表達式(表值函數或者子查詢)做爲APPLY語句的右錶鏈接左表。
2.因爲使用APPLY是老是先計算左表達式表,因此右表表達式可使用左表表達式中的列。
3.APPLY主要用於將表值函數運用在右表表達式中表的每一行。html

有時也APPLY將一個子查詢做爲左表表達式。假設咱們有如下的兩張表sql

order:
app

customer:函數

 

選出customer C001最近的N個訂單可使用inner join性能

SELECT TOP (N) CustomName,OrderId,CreateTime
    FROM dbo.Customer c
        INNER JOIN dbo.[Order] o
            ON o.CustomId=c.CustomId
            AND o.CustomId='C001'
    ORDER BY o.CreateTime DESC

可是要選出每一個 customer最近的N個訂單(TOP N per Group problem)單單靠inner
join就無能爲力了,可是經過CTE和ROW_NUMBER()的輔助能夠解決這個問題spa

WITH OrderedOrders AS 
( 
SELECT c.CustomName
       ,o.OrderId
       ,ROW_NUMBER() OVER (PARTITION BY c.CustomId ORDER BY o.CreateTime DESC) AS CustomOrder 
    FROM dbo.[Order] AS o
        INNER JOIN dbo.Customer AS c
        ON o.CustomId = c.CustomId
) 
SELECT o1.OrderId,o2.CustomName
    FROM dbo.[Order] AS o1
        INNER JOIN OrderedOrders AS o2 
        ON o1.OrderId = o2.OrderId
WHERE o2.CustomOrder <= N

這個查詢比較難讀,並且不天然。下面來看看使用CROSS APPLY的版本code

SELECT TopNOrder.OrderId,c.CustomName
    FROM dbo.Customer AS c
        CROSS APPLY(
            SELECT TOP (N) o.OrderId
                FROM dbo.[Order] o
                    WHERE c.CustomId=o.CustomId
                ORDER BY o.CreateTime DESC    
) AS TopNOrder

使用APPLY讓這個查詢看起來更加的天然。
而更天然的方式正如http://technet.microsoft.com/zh-cn/library/ms175156(v=sql.105).aspx提到的server

「使用APLLY運算符能夠爲實現查詢操做的外部表表達式返回的每一個行調用表值函數。表值函數做爲右輸入,外部表表達式做爲左輸入。」htm

咱們應該將TOP N的邏輯放在一個表值函數中,經過APPLY將這個表值函數運用在左輸入中的每一行。blog

下面來建立一個內聯的SQL Server函數

CREATE FUNCTION dbo.TopNOrder(@N int,@customerID varchar(50)) RETURNS TABLE 
AS RETURN
( 
SELECT TOP (@N) o.OrderId
  FROM dbo.[Order] AS o
    WHERE o.CustomId=@customerID
  ORDER BY o.CreateTime DESC
);

 

而後咱們能夠這樣使用,將返回和上面兩個查詢同樣的結果

SELECT TopNOrder.OrderId,c.CustomName FROM 
  dbo.Customer AS c
    CROSS APPLY dbo.TopNOrder(2,c.CustomId) AS TopNOrder

以上查詢當N爲2的結果爲

此外APPLY還能夠用OUTTER來修飾,效果相似於LEFT JOIN。
運行下面這個查詢,將沒有數據的customer Koo

SELECT TopNOrder.OrderId,c.CustomName FROM 
  dbo.Customer AS c
    OUTER APPLY dbo.TopNOrder(2,c.CustomId) AS TopNOrder

使用OUTER APPLY的結果爲

最後,APLLY還有更多能夠發掘的用法,在某些時候,能夠用APPLY來處理複雜的查詢和提升查詢的性能。但暫時先在這裏告一段落。
詳情能夠查看如下連接:
http://sqlmag.com/sql-server-2005/sql-server-2005s-apply-part-1
http://sqlmag.com/sql-server-2005/sql-server-2005s-apply-part-2
http://sqlblog.com/blogs/rob_farley/archive/2011/04/13/the-power-of-t-sql-s-apply-operator.aspx

相關文章
相關標籤/搜索