(011)每日SQL学习:SQL开窗函数
开窗函数:在开窗函数出现之前存在着很多用 SQL 语句很难解决的问题,很多都要通过复杂的相关子查询或者存储过程来完成。为了解决这些问题,在 2003 年 ISO SQL 标准加入了开窗函数,开窗函数的使用使得这些经典的难题可以被轻松的解决。目前在 MSSQLServer、Oracle、DB2 等主流数据库中都提供了对开窗函数的支持,不过非常遗憾的是 MYSQL 暂时还未对开窗函数给予支持。
开窗函数简介:与聚合函数一样,开窗函数也是对行集组进行聚合计算,但是它不像普通聚合函数那样每组只返回一个值,开窗函数可以为每组返回多个值,因为开窗函数所执行聚合计
算的行集组是窗口。在 ISO SQL 规定了这样的函数为开窗函数,在 Oracle 中则被称为分析函数。
数据表(Oracle):T_Person 表保存了人员信息,FName 字段为人员姓名,FCity 字段为人员所在的城市名,FAge 字段为人员年龄,FSalary 字段为人员工资
CREATE TABLE T_Person (FName VARCHAR2(20),FCity VARCHAR2(20),FAge INT,FSalary INT)
向 T_Person 表中插入一些演示数据:
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘Tom‘,‘BeiJing‘,20,3000);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘Tim‘,‘ChengDu‘,21,4000);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘Jim‘,‘BeiJing‘,22,3500);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘Lily‘,‘London‘,21,2000);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘John‘,‘NewYork‘,22,1000);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘YaoMing‘,‘BeiJing‘,20,3000);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘Swing‘,‘London‘,22,2000);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘Guo‘,‘NewYork‘,20,2800);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘YuQian‘,‘BeiJing‘,24,8000);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘Ketty‘,‘London‘,25,8500);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘Kitty‘,‘ChengDu‘,25,3000);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘Merry‘,‘BeiJing‘,23,3500);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘Smith‘,‘ChengDu‘,30,3000);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘Bill‘,‘BeiJing‘,25,2000);
INSERT INTO T_Person(FName,FCity,FAge,FSalary)
VALUES(‘Jerry‘,‘NewYork‘,24,3300);
select * from t_person:

要计算所有人员的总数,我们可以执行下面的 SQL 语句:SELECT COUNT(*) FROM T_Person
除了这种较简单的使用方式,有时需要从不在聚合函数中的行中访问这些聚合计算的值。比如我们想查询每个工资小于 5000 元的员工信息(城市以及年龄),并且在每行中都显示所有工资小于 5000 元的员工个数:
select fname,
fcity,
fsalary,
(select count(*) from t_person where fsalary < 5000) 工资少于5000员工总数
from t_person
where fsalary < 5000

虽然使用子查询能够解决这个问题,但是子查询的使用非常麻烦,使用开窗函数则可以大大简化实现,下面的 SQL 语句展示了如果使用开窗函数来实现同样的效果:
select fname, fcity, fsalary,5000
可以看到与聚合函数不同的是,开窗函数在聚合函数后增加了一个 OVER 关键字。
分区,并且计算当前行所属的组的聚合计算结果。比如对于FName等于 Tom的行,它所属的城市是BeiJing,同
属于BeiJing的人员一共有6个,所以对于这一列的显示结果为6。
这就不需要先对fcity分组求和,然后再和t_person表连接查询了,省事儿。

在同一个SELECT语句中可以 ORDER BY子句:
开窗函数中可以在OVER关键字后的选项中使用1000+2000+2000+2000 ”)。
下边这的估计不常用:
例子程序三:
SELECT FName,
FSalary,
SUM(FSalary) OVER(ORDER BY FSalary ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) 前二后二和
FROM T_Person;

这里的开窗函数“SUM(FSalary) OVER(ORDER BY FSalary ROWS BETWEEN 2
PRECEDING AND 2 FOLLOWING)”表示按照FSalary进行排序,然后计算从当前行前两行(2
PRECEDING)到当前行后两行(2 FOLLOWING)的工资和,注意对于第一条和第二条而言它们
的“前两行”是不存在或者不完整的,因此计算的时候也是要按照前两行是不存在或者不完整进
行计算,同样对于最后两行数据而言它们的“后两行”也不存在或者不完整的,同样要进行类似
的处理。
例子程序四:
SELECT FName, FSalary,
SUM(FSalary) OVER(ORDER BY FSalary ROWS BETWEEN 1 FOLLOWING AND 3 FOLLOWING) 后面一到三之和
FROM T_Person;

这里的开窗函数“SUM(FSalary) OVER(ORDER BY FSalary ROWS BETWEEN 1
FOLLOWING AND 3 FOLLOWING)”表示按照FSalary进行排序,然后计算从当前行后一行(1
FOLLOWING)到后三行(3 FOLLOWING)的工资和。注意最后一行没有后续行,其计算结果为
空值NULL而非0。
例子程序五:算工资排名
SELECT FName, FSalary,
COUNT(*) OVER(ORDER BY FSalary ROWS BETWEEN UNBOUNDED PRECEDING AND
CURRENT ROW)
FROM T_Person;

这里的开窗函数“COUNT(*) OVER(ORDER BY FSalary RANGE BETWEEN UNBOUNDED
PRECEDING AND CURRENT ROW)”表示按照FSalary进行排序,然后计算从第一行
(UNBOUNDED PRECEDING)到当前行(CURRENT ROW)的人员的个数,这个可以看作是计算
人员的工资水平排名。
不再用ROWNUM 了 省事了。这个over简写就会出错。
例子程序6:结合max求到目前行的最大值
SELECT FName, FSalary,FAge,
MAX(FSalary) OVER(ORDER BY FAge) 此行之前最大值
FROM T_Person;

这里的开窗函数“MAX(FSalary) OVER(ORDER BY FAge)”是“MAX(FSalary)
OVER(ORDER BY FAge RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)”
的简化写法,它表示按照FSalary进行排序,然后计算从第一行(UNBOUNDED PRECEDING)
到当前行(CURRENT ROW)的人员的最大工资值。
例子程序6:over(partition by XX order by XX) partition by和order by 结合
员工信息+同龄人最高工资,按工资排序
SELECT FName, FSalary,FAge,
MAX(FSalary) OVER(PARTITION BY FAge ) 同龄人最高工资
FROM T_Person;
--原文写法
SELECT FName, FSalary,FAge,
MAX(FSalary) OVER(PARTITION BY FAge order by Fsalsry ) 同龄人最高工资
FROM T_Person;
--个人觉得显示有点问题,order by 之后最高工资就变成了每个人的工资显示。并不是同龄人的最高工资显示

PARTITION BY子句和ORDER BY 可以 共 同 使用,从 而 可以 实现 更 加复 杂 的 功能。
原文地址:http://www.mamicode.com/info-detail-1774214.html
(011)每日SQL学习:SQL开窗函数的更多相关文章
- SQL SERVER:开窗函数 SUM() OVER() 数据统计中一例使用
由于前一段时间胃痛,导致博客园博客都停更了一个月左右.近几天,胃病终于稍微有所好转,决定重新写博文. 前几天,有个朋友刚好问到本人有关 SQL 语句,大致是原表有两列,分别为月份.月份销售额,而需要一 ...
- sql语句中开窗函数的使用
开窗函数主要分为2类: 1.排序开窗函数: rank() over(partition by xxx order by yyy) //各分区按照yyy字段排序,如果yyy字段值一样,则rank值一样, ...
- SQL Server 2012 - 开窗函数
-- 开窗函数:在结果集的基础上进一步处理(聚合操作) -- Over函数,添加一个字段显示最大年龄 SELECT * , MAX(StuAge) OVER ( ) MaxStuAge FROM db ...
- SQL学习_时间函数
最近测试报表需要统计不同时间段的列表记录,收集一些时间函数作为参考,原文地址:http://blog.csdn.net/lyzlyfok/article/details/6282509 sql ser ...
- SQL学习笔记:函数
SQL函数 AVG select AVG(col) AS avgvalue from tablename select col2 from tablename where col1>(selec ...
- sql server利用开窗函数over() 进行分组统计
这是一道常见的面试题,在实际项目中经常会用到. 需求:求出以产品类别为分组,各个分组里价格最高的产品信息. 实现过程如下: declare @t table( ProductID int, Produ ...
- PL/SQL学习笔记之函数
一:函数 函数与过程的最大不同就是,函数有返回值.适用于需要返回结果的场景. 二:创建函数 CREATE [OR REPLACE] FUNCTION function_name [(parameter ...
- SQL学习记录:函数(二)
字符串函数 1.获取字符的ASCII码 语法结构: ASCII(espression) 这里的expression是一个返回char或varchar数据类型的表达式,ASCII函数仅对表达式最左 ...
- SQL学习-SQL Server
- SQL SERVER开窗函数
作为一名开发人员来讲,我感觉在职场白混了好多年,可能是自己真的没有进取的精神吧,看了<程序员的SQL金典>这本电子书,真的让我学到了不少知识,真心喜欢这本电子书,书中讲解的内容比较好懂,也 ...
随机推荐
- mysql存储过程定义者
1. 执行update mysql.proc set DEFINER='root@%' WHERE NAME='p_update_rim_batch_log' AND db='otherdataonl ...
- 常见数据库的JDBC URL
转自:http://blog.csdn.net/ring0hx/article/details/6152528 Microsoft SQL Server Microsoft SQL Server JD ...
- Hadoop之WordCount
求平均数是MapReduce比较常见的算法,求平均数的算法也比较简单,一种思路是Map端读取数据,在数据输入到Reduce之前先经过shuffle,将map函数输出的key值相同的所有的value值形 ...
- 当会打王者荣耀的AI学会踢足球,一不小心拿下世界冠军!
难得的元旦小假期,没有什么比得上在慵懒的冬日艳阳下放松自己,拿起手机,叫上了许久未一起作战的小伙伴,到王者荣耀中激战了一番,仿佛又回到了当年那个年轻的自己. 厉害不,毕竟当年DD也是王者五十星的水平, ...
- jpa 主键重复导致查询list的数据总是重复第一条数据
背境: JPA 读取 Oracle 中的视图,同一条sql, 在数据库 IDE (PLSql)读出 878 条记录并正常显示,代码依然保存了 878 条记录,但所有记录均一样,即数据库中第一条记录. ...
- Android基本组件TextView和EditView
1.TextView 用于在屏幕上显示文本,可以显示单行文本,多行文本,和带图像的文本. 常用xml属性 (1)android:autoLink,用于指定是否将指定的文本转换为可单机的超链接形式,其属 ...
- 论文阅读 Characterization of Multiple 3D LiDARs for Localization and Mapping using Normal Distributions Transform
Abstract 在这个文章里, 我们细致的比较了10种不同的3D LiDAR传感器, 用了一般的 Normal Distributions Transform (NDT) 算法. 我们按以下几个任务 ...
- 风炫安全WEB安全学习第二十一节课 存储型XSS讲解
风炫安全WEB安全学习第二十一节课 存储型XSS讲解 存储型XSS演示 存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存 ...
- R语言学习笔记-Corrplot相关性分析
示例图像 首先安装需要的包 install.packages("Corrplot") #安装Corrplot install.packages("RColorBrewer ...
- DM TDD使用小结
1.搭建流程 1.1 ss初始化及启动 --->1节点: cd /dm/bin ./dmdssinit path=/dm/data inst=ss1 port=35300 REGION_SIZE ...