SQL SERVER开窗函数
作为一名开发人员来讲,我感觉在职场白混了好多年,可能是自己真的没有进取的精神吧,看了《程序员的SQL金典》这本电子书,真的让我学到了不少知识,真心喜欢这本电子书,书中讲解的内容比较好懂,也比较实用。谢谢作者的辛勤汗水:)。
今天将要介绍SQL Sever的开窗函数,何谓开窗函数,不懂吧。反正对于我来说,我是摸不着头脑了,第一次听说过。那么,什么是开窗函数,其实可以理解为是聚合函数的一个加强版。因为使用聚合函数的话(不包括子查询的情况),整个查询都只能是聚合列返回值,而不能有基础行的返回值。那么对于需要基础行的返回值的话,就需要使用复杂的子查询或者是存储过程等才可以解决。但是使用开窗函数就可以轻松解决,它能够在同一行中同时返回基础行的列和聚合列。在ISO SQL规定了这样的函数为开窗函数,在Oracle中则被称为分析函数,而在DB2中则被称为OLAP函数。
开窗函数与聚合函数一样,都是对行的集合组进行聚合计算。它用于为行定义一个窗口(这里的窗口是指运算将要操作的行的集合),它对一组值进行操作,不需要使用GROUP BY子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列。反正我理解这个函数已经使用好子查询或者是其它方式求得聚合列的值给我合并。
以书中的例子一步一步来介绍,假设要计算所有人员的总数,我们可以执行下面的SQL语句:
SELECT COUNT(FName) FROM T_Person
这种方式比较直接,只返回一个聚合列的值,没有任何基础行的列的值。但是有时需要从不在聚合函数中的行的列中访问这些聚合计算的值(即基础行的列)。比如我们想查询每个工资小于5000元的员工信息(城市以及年龄),并且在每行中都显示所有工资小于5000 元的员工个数,尝试编写下面的SQL语句:
SELECT FName, FCITY, FAGE, FSalary, COUNT(FName)
FROM T_Person
WHERE FSALARY<5000
执行上面的SQL以后我们会得到下面的错误信息:
选择列表中的列'T_Person.FCity' 无效,因为该列没有包含在聚合函数或GROUP BY 子句中。
这是因为所有不包含在聚合函数中的列必须声明在GROUP BY 子句中,使用子查询的方式是可以解决:
SELECT FName, FCITY, FAGE, FSalary,
(
SELECT COUNT(FName) FROM T_Person
WHERE FSALARY<5000
)
FROM T_Person
WHERE FSALARY<5000
虽然使用子查询能够解决这个问题,但是子查询的使用非常麻烦,使用开窗函数则可以大大简化实现,下面的SQL语句展示了如果使用开窗函数来实现同样的效果:
SELECT FName, FCITY, FAGE, FSalary, COUNT(FName) OVER()
FROM T_Person
WHERE FSALARY<5000
可以看到与聚合函数不同的是,开窗函数在聚合函数后增加了一个OVER关键字。
开窗函数的调用格式为:函数名(列) OVER(选项)
我这里使用的是SQL Server 2008 R2,不知道从什么时候开始,SQL SERVER也支持开窗函数中使用ORDER BY子句(注:书本中说MSSQLServer中是不支持开窗函数中使用ORDER BY子句)。不管怎么样,这里我整合了网上的相关内容。也正因为开窗函数支持了ORDER BY子句之后,开窗函数被分为两大类。
第一大类:聚合开窗函数====》聚合函数(列) OVER (选项),这里的选项可以是PARTITION BY子句,但不可是ORDER BY子句
第二大类:排序开窗函数====》排序函数(列) OVER(选项),这里的选项可以是ORDER BY子句,也可以是 OVER(PARTITION BY子句 ORDER BY子句),但不可以是PARTITION BY子句
| 聚合开窗函数 |
OVER 关键字表示把聚合函数当成聚合开窗函数而不是聚合函数。SQL 标准允许将所有聚合函数用做聚合开窗函数。
在上边的例子中,开窗函数COUNT(*) OVER()对于查询结果的每一行都返回所有符合条件的行的条数。OVER关键字后的括号中还经常添加选项用以改变进行聚合运算的窗口范围。如果OVER关键字后的括号中的选项为空,则开窗函数会对结果集中的所有行进行聚合运算。
| PARTITION BY 子句 |
开窗函数的OVER关键字后括号中的可以使用PARTITION BY 子句来定义行的分区来供进行聚合计算。与GROUP BY 子句不同,PARTITION BY 子句创建的分区是独立于结果集的,创建的分区只是供进行聚合计算的,而且不同的开窗函数所创建的分区也不互相影响。下面的SQL语句用于显示每一个人员的信息以及所属城市的人员数:
SELECT FName, FCITY, FAGE, FSalary,
COUNT(FName) OVER(PARTITION BY FCITY)
FROM T_Person
OVER(PARTITION BY FCITY)表示对结果集按照FCITY进行分区,并且计算当前行所属的组的聚合计算结果。在同一个SELECT语句中可以同时使用多个开窗函数,而且这些开窗函数并不会相互干扰。比如下面的SQL语句用于显示每一个人员的信息、所属城市的人员数以及同龄人的人数:
SELECT FName,FCITY, FAGE, FSalary,
COUNT(FName) OVER(PARTITION BY FCITY),
COUNT(FName) OVER(PARTITION BY FAGE)
FROM T_Person
| 排序开窗函数 |
对于排序开窗函数来讲,它支持的开窗函数分别为:ROW_NUMBER(行号)、RANK(排名)、DENSE_RANK(密集排名)和NTILE(分组排名)。
先看一段SQL语句:
select FName, FSalary, FCity, FAge,
row_number() over(order by FSalary) as rownum,
rank() over(order by FSalary) as rank,
dense_rank() over(order by FSalary) as dense_rank,
ntile(6) over(order by FSalary)as ntile
from T_Person
order by FName
执行的结果如下(对于想自己尝试的朋友,那你得辛苦点,下载电子书或者是购买书来学习吧。因为我可是限于篇幅,省略去大部分内容哦):

看到上面的结果了吧,下面来介绍下相关的内容。我们得到的最终结果是按照FName进行升序显示的。
对于row_number() over(order by FSalary) as rownum来说,这个排序开窗函数是按FSalary升序的方式来排序,并得出排序结果的序号
对于rank() over(order by FSalary) as rank来说,这个排序形容函数是按FSalary升序的方式来排序,并得出排序结果的排名号。这个函数求出来的排名结果可以排列,并列排名之后的排名将是并列的排名加上并列数(简单说每个人只有一种排名,然后出现两个并列第一名的情况,这时候排在两个第一名后面的人将是第三名,也就是没有了第二名,但是有两个第一名)
对于dense_rank() over(order by FSalary) as dense_rank来说,这个排序函数是按FSalary升序的方式来排序,并得出排序结果的排名号。这个函数与rand()函数不同在于,并列排名之后的排名只是并列排名加1(简单说每个人只有一种排名,然后出现两个并列第一名的情况,这时候排在两个第一名后面的人将是第二名,也就是两个第一名,一个第二名)
对于ntile(6) over(order by FSalary)as ntile 来说,这个排序函数是按FSalary升序的方式来排序,并得出排序结果的分组数。
排序函数和聚合开窗函数类似,也支持在OVER子句中使用PARTITION BY语句。例如:
select FName, FSalary, FCity, FAge,
row_number() over(partition by FName order by FSalary) as rownum,
rank() over(partition by FName order by FSalary) as rank,
dense_rank() over(partition by FName order by FSalary) as dense_rank,
ntile(6) over(partition by FName order by FSalary)as ntile
from T_Person
order by FName
关于PARTITION BY子句,请看上面的介绍,这里就不再累赘了。但是需要注意一点的是,在排序开窗函数中使用PARTITION BY子句需要放置在ORDER BY子句之前。
至此本文完。
SQL SERVER开窗函数的更多相关文章
- SQL ServerOVER 子句,over开窗函数,SQL SERVER 开窗函数
https://technet.microsoft.com/zh-cn/library/ms189461(v=sql.105).aspx http://www.cnblogs.com/85538649 ...
- 【转】SQL SERVER 开窗函数简介
在SQL SERVER 2005/2008支持两种排名开窗函数和聚集开窗函数. 以SQL SERVER中分面页为例,按时间顺序列出定单号. WITH OrderInfo AS ( SELECT ROW ...
- Sql server 开窗函数over()的语法
用法一:与ROW_NUMBER()函数结合用,给结果进行排序编号,如图: 代码如下: SELECT ROW_NUMBER() over(order by RequiredDate) num ,* fr ...
- Sql Server 开窗函数Over()的使用
利用over(),将统计信息计算出来,然后直接筛选结果集 declare @t table( ProductID int, ProductName ), ProductType ), Price in ...
- SQL Server - 开窗函数
-- 开窗函数:在结果集的基础上进一步处理(聚合操作) SELECT * FROM dbo.Student S# Sname Sage Ssex ---------- ---------- ----- ...
- SQL Server开窗函数之OVER子句、PARTITION BY 子句
开窗函数与聚合函数一样,都是对行的集合组进行聚合计算.它用于为行定义一个窗口(这里的窗口是指运算将要操作的行的集合),它对一组值进行操作,不需要使用GROUP BY子句对数据进行分组,能够在同一行中同 ...
- SQL Server 聚合函数算法优化技巧
Sql server聚合函数在实际工作中应对各种需求使用的还是很广泛的,对于聚合函数的优化自然也就成为了一个重点,一个程序优化的好不好直接决定了这个程序的声明周期.Sql server聚合函数对一组值 ...
- SQL Server排序函数row_number和rank的区别
SQL Server排序函数row_number和rank的区别 直接看测试结果 declare @table table(name varchar(100),amount int, memo var ...
- 数据库开发基础-SQl Server 聚合函数、数学函数、字符串函数、时间日期函数
SQL 拥有很多可用于计数和计算的内建函数. 函数的语法 内建 SQL 函数的语法是: SELECT function(列) FROM 表 函数的类型 在 SQL 中,基本的函数类型和种类有若干种.函 ...
随机推荐
- Type 'System.IO.FileStream' with data contract name 'FileStream:http://schemas.datacontract.org/2004/07/System.IO' is not expected.
今天在WCF项目里使用DataContract序列化接口参数的时候,报了这个错,错误详细信息如下: System.ServiceModel.CommunicationException: There ...
- 跨frame操作dom元素
今天,一群友问到跨frame操作dom元素的问题.于是写了个demo,在此发表在博客里面,供其他同道中人参考! 创建child.html内容如下: <!DOCTYPE HTML PUBLIC & ...
- 精简DropDownList用法
ViewBag.TypeID = new SelectList(db.TType, "ID", "Name", model.TypeID); @Html.Dro ...
- ABAP OO与ALV结合方式探索(1)
用OO来开发,尤其是在复杂业务的开发过程中 从程序设计的角度而言,应该更简单一点 而ALV是二次开发中登场很高的一个控件 最近做了一些尝试,探索OO的代码和ALV的结合使用 使用控件型的ALV A ...
- iOS屏幕尺寸和分辨率
iOS平台家族成员主要包括iPhone.iPod Touch和iPad,但是各类设备的分辨率各不相同,目前存在的尺寸主要有: iOS设备的尺寸多种多样,此外,屏幕的分辨率也有多种,总结如下表所示: 其 ...
- jquery 1.6发布后,增加prop()方法部分取代attr()方法
以前的jq中,全部使用attr来访问对象的属性,比如取一个图片的alt属性,就可以这样做$('#img').attr('alt'); 但是在某些时候,比如访问checkbox的disabled属性 ...
- php读取excel文件的实例代码
php读取excel文件的实例代码. 代码: <?php /** * php读取excel文件 * by www.jbxue.com */ $this->loadexcel();//半酣p ...
- php文本操作方法集合比较第2页
fgets和fputs.fread和fwrite.fscanf和fprintf 格式化读写函数fscanf和fprintf fscanf函数,fprintf函数与前面使用的scanf和printf 函 ...
- 你必须知道的.NET
作者博客地址:http://www.cnblogs.com/anytao/archive/2008/04/09/anytao_insidenet_center.html 第1章 OO大智慧 1.1对象 ...
- Oracle 表的连接方式(2)-----HASH JOIN的基本机制2
Hash算法原理 对于什么是Hash算法原理?这个问题有点难度,不是很好说清楚,来做一个比喻吧:我们有很多的小猪,每个的体重都不一样,假设体重分布比较平均(我们考虑到公斤级别),我们按照体重来分,划分 ...