Sql Server中不常用的表运算符之APPLY(1)中提到,SQL2005中新支持的APPLY的特性:
1.可以直接将表表达式(表值函数或者子查询)作为APPLY语句的右表连接左表。
2.由于使用APPLY是总是先计算左表达式表,所以右表表达式可以使用左表表达式中的列。
3.APPLY主要用于将表值函数运用在右表表达式中表的每一行。

有时也APPLY将一个子查询作为左表表达式。假设我们有以下的两张表

order:

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()的辅助可以解决这个问题

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的版本

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提到的

“使用APLLY运算符可以为实现查询操作的外部表表达式返回的每个行调用表值函数。表值函数作为右输入,外部表表达式作为左输入。”

我们应该将TOP N的逻辑放在一个表值函数中,通过APPLY将这个表值函数运用在左输入中的每一行。

下面来创建一个内联的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

Sql Server中不常用的表运算符之APPLY(2)的更多相关文章

  1. Sql Server中不常用的表运算符之APPLY(1)

    写在这个系列的前面: 就像他们的名字一样,作为一个表运算,他们用来运算左表和右表.JOIN也是一个表运算符,不过他太常用了. APPLY: 将右表表达式应用在左表的每一行上. APPLY是Sql200 ...

  2. Sql Server中不常用的表运算符之UNPIVOT

    在Sql Server中不常用的表运算符之PIVOT中,介绍了PIVOT表运算符,现在来说说与之相对应的另一个表运算符UNPIVOT. 从名字可以看出,这个运算符的作用与PIVOT刚好相反,是将一行的 ...

  3. Sql Server中不常用的表运算符之PIVOT

    PIVOT是SQL Server2005新添加的一个表运算符,作用在于将行转为列. 先来看看他的基本语法: 来自http://technet.microsoft.com/zh-cn/library/m ...

  4. SQL Server中,常用的全局变量

    在SQL Server中,全局变量是一种特殊类型的变量,服务器将维护这些变量的值.全局变量以@@前缀开头,不必进行声明,它们属于系统定义的函数.下表就是SQL Server中一些常用的全局变量. 全局 ...

  5. SQL Server中查询数据库及表的信息语句

    /* -- 本文件主要是汇总了 Microsoft SQL Server 中有关数据库与表的相关信息查询语句. -- 下面的查询语句中一般给出两种查询方法, -- A方法访问系统表,适应于SQL 20 ...

  6. SQL Server中的临时表和表变量

    SQL Server中的临时表和表变量 作者:DrillChina出处:blog2008-07-08 10:05 在SQL Server的性能调优中,有一个不可比拟的问题:那就是如何在一段需要长时间的 ...

  7. sql Server中临时表与数据表的区别

    sql server 中临时表与数据表的区别 1.如何判断临时表和数据表已生成 --如何判断临时表是否已创建--- if exists(select * from tempdb..sysobjects ...

  8. 转:Sql Server中清空所有数据表中的记录

    如果要删除数据表中所有数据只要遍历一下数据库再删除就可以了,清除所有数据我们可以使用搜索出所有表名,构造为一条SQL语句进行清除了,这里我一一给各位同学介绍.   使用sql删除数据库中所有表是不难的 ...

  9. Sql Server中清空所有数据表中的记录

    Sql Server中清空所有数据表中的记录 清空所有数据表中的记录: 代码如下:exec sp_msforeachtable  @Command1 ='truncate table ?'删除所有数据 ...

随机推荐

  1. 条款19:设计class犹如设计type

    1,新的type对象应该如何被创建和销毁? 这会影响class的构造函数ctor和析构函数dtor,以及内存分配函数和释放函数   //operator new //operator new[] // ...

  2. C#中Validating和Validated事件

    http://blog.sina.com.cn/s/blog_6116673a0100fpeo.html 待解读

  3. WebApi 学习随笔(一)

    引用MSDN: ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad ...

  4. OAF_开发系列02_实现OAF页面的通过个性化多语言开发国际化(案例)

    2014-06-10 Created By BaoXinjian

  5. error: L6235E: More than one section matches selector - cannot all be FIRST/LAST

    解决措施http://blog.csdn.net/chenbang110/article/details/7586244

  6. java和h5 canvas德州扑克开发中(二)

    德州扑克网页源码在github上分享 https://github.com/lxr1907/pokers 感兴趣的可以上去看下. 1.通讯使用websocket,主要在message.js中. 2.用 ...

  7. TensorFlow中max pooling层各参数的意义

    官方教程中没有解释pooling层各参数的意义,找了很久终于找到,在tensorflow/python/ops/gen_nn_ops.py中有写: def _max_pool(input, ksize ...

  8. C++模板机制总结

    模板是C++中非常重要的组成部分,之前自己对这块领域一直不太熟悉.最近趁着有时间学习了一下,特此总结. 首先是函数模板,它的定义方式如例子所示: template <typename T> ...

  9. Linux disk_partition_dev_马士兵_note

    一般装Linux会遇到的问题: 找不到硬件驱动 现在主流的一些硬件 不支持Linux驱动   尽量找主流的硬件,尽量找老一点的硬件   装系统: 1.记下 系统 ---->到时候要找驱动   2 ...

  10. Linux 命令与文件的搜寻

    平时会偶尔忘记一些命令或者文件,下面的这些命令能够帮我们快速的找到命令或者文件 1. 命令的搜寻 命令:which 功能:在PATH配置的目录下搜寻命令 用法:which [-a] [command] ...