Sql Server中不常用的表运算符之APPLY(2)
在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)的更多相关文章
- Sql Server中不常用的表运算符之APPLY(1)
写在这个系列的前面: 就像他们的名字一样,作为一个表运算,他们用来运算左表和右表.JOIN也是一个表运算符,不过他太常用了. APPLY: 将右表表达式应用在左表的每一行上. APPLY是Sql200 ...
- Sql Server中不常用的表运算符之UNPIVOT
在Sql Server中不常用的表运算符之PIVOT中,介绍了PIVOT表运算符,现在来说说与之相对应的另一个表运算符UNPIVOT. 从名字可以看出,这个运算符的作用与PIVOT刚好相反,是将一行的 ...
- Sql Server中不常用的表运算符之PIVOT
PIVOT是SQL Server2005新添加的一个表运算符,作用在于将行转为列. 先来看看他的基本语法: 来自http://technet.microsoft.com/zh-cn/library/m ...
- SQL Server中,常用的全局变量
在SQL Server中,全局变量是一种特殊类型的变量,服务器将维护这些变量的值.全局变量以@@前缀开头,不必进行声明,它们属于系统定义的函数.下表就是SQL Server中一些常用的全局变量. 全局 ...
- SQL Server中查询数据库及表的信息语句
/* -- 本文件主要是汇总了 Microsoft SQL Server 中有关数据库与表的相关信息查询语句. -- 下面的查询语句中一般给出两种查询方法, -- A方法访问系统表,适应于SQL 20 ...
- SQL Server中的临时表和表变量
SQL Server中的临时表和表变量 作者:DrillChina出处:blog2008-07-08 10:05 在SQL Server的性能调优中,有一个不可比拟的问题:那就是如何在一段需要长时间的 ...
- sql Server中临时表与数据表的区别
sql server 中临时表与数据表的区别 1.如何判断临时表和数据表已生成 --如何判断临时表是否已创建--- if exists(select * from tempdb..sysobjects ...
- 转:Sql Server中清空所有数据表中的记录
如果要删除数据表中所有数据只要遍历一下数据库再删除就可以了,清除所有数据我们可以使用搜索出所有表名,构造为一条SQL语句进行清除了,这里我一一给各位同学介绍. 使用sql删除数据库中所有表是不难的 ...
- Sql Server中清空所有数据表中的记录
Sql Server中清空所有数据表中的记录 清空所有数据表中的记录: 代码如下:exec sp_msforeachtable @Command1 ='truncate table ?'删除所有数据 ...
随机推荐
- Inno Setup制作安装包的几个问题
1. 卸载时,如何判断应用程序是否运行 InnoSetup 提供变量AppMutex,用来保存应用程序的Mutex名称.现在很多应用程序都是唯一实例运行.这样避免配置文件被错误修改以及其他很多衍 ...
- 解决ie6下不支持fix属性,模拟固定定位
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
- 如何在Ubuntu下的VirtualBox虚拟机(Windows XP)里挂载/使用U盘 (转载)
文章来源:http://www.codelast.com/ 在Ubuntu下安装了VirtualBox之后,如果你的虚拟机安装的是Windows XP系统,那么,你会发现,当你插上U盘时,无论你怎么折 ...
- npoi本地文件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...
- javascript中日期格式与时间戳之间的转化
日期格式与时间戳之间的转化 一:日期格式转化为时间戳 function timeTodate(date) { var new_str = date.replace(/:/g,'-'); new_str ...
- JSP EL表达式(转)
一.EL简介 1.语法结构 ${expression}2.[]与.运算符 EL 提供.和[]两种运算符来存取数据. 当要存取的属性名称中包含一些特殊字符,如.或?等并非字母或数字 ...
- hadoop 完全分布式 下 datanode无法启动解决方法
问题描述: 在集群模式下更改节点后,启动集群发现 datanode一直启动不起来. 我集群配置:有5个节点,分别为master slave1-5 . 在master以Hadoop用户执行:start- ...
- Error:The network adaptor could not establish the connection问题的解决办法
最近在学习hibernate 5.0.4, 自然而然就需要使用数据库,由于本人工作中一直使用Oracle,于是在自己的电脑上安装了Oracle 12.1.0, 安装完成使用一直没有问题,突然有一天使 ...
- java中interface的详解
JAVA的核心概念:接口(interface) 接口与类属于同一层次,实际上,接口是一种特殊的抽象类. 如: interface IA{ } public interface: 公开接口 与 ...
- rman datafile恢复(归档模式)
模拟环境 1. 做操作之前先备份数据库 RMAN> run { # Hot database level 0 whole backup allocate channel t1 typ ...