1、窗口函数入门
(1)窗口函数的作用于由over子句定义的数据行集合
(2)窗口函数主要用于分析目的、汇总计算、移动平均值计算、计算数据差、发现数据岛等
(3)这些函数都是基于标准sql(ISO 和 ANSI 标准)
(4)其概念的精髓在于可以通过对数据行集合或数据行窗口进行多种计算,最后得到单个值
(5)窗口函数让我们以更加轻松、直观、高效的方式解决数据行集合计算和分析问题
(6)窗口函数是SQL 查询的未来方向,值得学习
2、排名窗口的背景
2.1窗口函数的描述
(1)窗口函数作用于一个数据行集合。窗口是标准sql术语,用来描述sql语句中用over子句划定的内容,这个内容就是窗口函数的作用域
(2)对于结果集的每一行,Over子句都定义一个与之对应的独立窗口
-- 使用rank函数、更具val降序排序,并输出排名 SELECT orderid, orderdate, val, RANK() OVER(ORDER BY val DESC) AS rnk FROM Sales.OrderValues ORDER BY rnk;
(3)标准SQL第一次支持窗口函数是在SQL:1999的拓展文档,此时称为“OLAP”,最新的SQL 标准中已经有了非常丰富和全面的窗口函数了
(4)标准SQL支持几种窗口函数类型: 集合、排序 、分布、 偏移
(5)聚集窗口函数就是常用的Sum、Count 、Min 、Max 等函数,一个聚集函数的作用域就是一个记录集 、这个记录集由查询分组、或窗口描述来定义
(6)排名函数有rank 、dense_rank、 row_number、 ntile ,SQL 标准中将前两个和后两个归于不同类型
(7)分布函数有percent_rank、cume_dist、percentile_count 、percentile_disc ,这四个函数从sql server 2012 开始引入
(8)窗口函数的具体应用: 分页、去重、返回前n条数据、计算累积合计、对时间间隔进行操作、统计最大并发会话数、找出数据差距(gap)、找数据岛(island)、计算百分比、计算分布模式、排序层次结构、数据透视、计算时效性、计算近因
3、窗口函数中的元素
窗口函数的行为描述出现在Over子句中,涉及3个元素、分区、排序、框架
3.1 分区(partition by)
(1)分区元素使得将我们的窗口范围限制为只与当前行的分区特性(分区列)值相等的行集
(2)理解分区,要理解分区的过滤、赛选 窗口行集
3.2排序
(1)排序元素定义计算的顺序,且定义的是分区内的顺序
(2)sql server 对聚合函数中排序的支持是从sqlserver2012开始的
3.3框架
(1) 从本质上来说,框架是一个在分区内对行进一步限制的赛选器
(2) 框架是在窗口使用partition 过滤,然后使用order by 排序之后,进一步限制范围
(3)sql server 2012开始支持框架
(4)框架限制格式略,其实是指定上下界,上下界通过当前行的偏移量来指定
4、支持窗口函数的查询元素
并不是所有的查询子句都支持窗口函数、只有select 和 orderby子句支持,这是为了避免二义性(“同时执行的原因,导致结果不确定”),把查询结果(几乎是)当成窗口的起点
5、聚合窗口函数
5.1聚合窗口函数描述
(1)窗口聚合函数和分组聚合函数的功能是相同的,一个聚合函数作用于一个行集上,使用什么语言机制来定义不重要
(2)在标准sql 中聚合窗口函数支持三种元素,分区、排序、框架,这三种元素的目的都是对窗口内的行进行过滤
(3)当不对窗口进行任何限制的时候,即over子句后面的括号为空,select 的结果集 直接 作为窗口函数的输入
5.2聚合与分区
查看一个例子,体验聚合函数作用的窗口使用与没有使用分区过滤过滤的区别
-- default and explicit partitioning USE TSQL2012; SELECT orderid, custid, val, SUM(val) OVER() AS sumall, SUM(val) OVER(PARTITION BY custid) AS sumcust FROM Sales.OrderValues AS O1; /* orderid custid val sumall sumcust -------- ------- ------- ----------- -------- 10643 1 814.50 1265793.22 4273.00 10692 1 878.00 1265793.22 4273.00 10702 1 330.00 1265793.22 4273.00 10835 1 845.80 1265793.22 4273.00 10952 1 471.20 1265793.22 4273.00 11011 1 933.50 1265793.22 4273.00 10926 2 514.40 1265793.22 1402.95 10759 2 320.00 1265793.22 1402.95 10625 2 479.75 1265793.22 1402.95 10308 2 88.80 1265793.22 1402.95 ... */
6、排名窗口函数
6.1 row_number()
(1)row_number()根据over子句中order by 排序结果,分配连续递增整数
(2)order by 排序元素值相等的两列,即使值没有增加,row_number()也增加、即row_number()必须生成唯一值、即使排序值有相等情况
6.2 rank()
(1) rank 是在分区范围内比较排序值的大小,返回 大于或小于当前排序值的记录个数+1
(2)根据上诉逻辑,当不同记录拥有相同的逻辑排序值,那么rank 返回的排名值相等,这与row_number 相等
6.3dense_rank()
(1)dense_rank() 处理逻辑类似rank,都是比较值,取个数,因此当排序值相等,排名值也相等
(2)dense_rank 与rank 的区别是,在计算个数的时候,rank 不去重,dense_rank ,会去重
6.4ntile 函数
(1)ntile 函数允许将结果中的行与大小相等的行组关联起来
(2)将分区分成多少个组,在函数输入总指定,如ntile(10),分成10个组
(3)返回row_number排序,分组之后的组号
7、偏移开窗函数
这个就是找当前行偏移指定行的数的值,用的少
8、聚合开窗函数
(1)支撑 分区、 排序 、框架
(2)和普通聚合函数没有区别,常规聚合作用了分组、开窗聚合聚合于窗口