在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