SQL ——窗口函数简介

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mzl87/article/details/84455076

目录

1、窗口函数的描述

2、窗口函数中的元素

2.1、分区

2.2、排序

2.3、框架

3、支持窗口函数的查询元素

4、窗口函数类别

4.1、排名函数

4.2、分布函数

4.3、偏移函数


1、窗口函数的描述

窗口函数作用于一个数据行集合。窗口是标准的SQL术语,用来描述SQL语句内OVER子句划定的内容,这个内容就是窗口函数的作用域。而在OVER子句中,定义了窗口所覆盖的与当前行相关的数据行集、行的排序及其他的相关元素。

标准SQL对窗口函数的第一次支持是在SQL:1999的扩展文档中,当时,它们称为“OLAP”函数。从那以后,每次标准版本的修订都会增强对窗口函数的支持,直到现在的SQL:2003、SQL:2008、SQL:2011。最新的SQL标准版本,已经有了非常丰富和全面的窗口函数,显示出标准委员会对这一概念的坚定,以及从更多窗口函数和更多功能两个方面持续增强支持标准。

2、窗口函数中的元素

窗口函数的行为描述出现在函数的OVER子句中,并涉及多个元素。3个核心元素分别是分区、排序和框架。不是所有的窗口函数都支持这3个元素。

2.1、分区

分区元素是由PARTITION BY子句定义,并被所有的窗口函数支持。他对当前计算的窗口函数进行限制,仅仅那些在结果集的分区列中与当前行有相同值的行才能进入窗口。如果没有指定PARTITION BY子句,窗口就没有限制。换种说法就是:如果没有显示指定分区,则默认分区就是把整个查询结果集当作一个分区。有一点不太明显,这里提出来:同一个查询中的不同函数,可能会有不同的分区描述。

2.2、排序

排序元素定义计算的顺序,如果与分区有关,则是在分区内的顺序。在标准的SQL中,所有函数都支持排序元素。起初SQL SERVER不支持聚合函数中的排序元素,而仅仅支持分区。对聚合函数红排序的支持,是从SQL SERVER 2012 开始的。

有趣的是,针对不同的函数类别,排序元素有轻微的不同意义。对于排名函数,排序是直观的。而聚合窗口函数的排序和排名窗口的排序略有意义上的不同。在聚合中,与某些人认为的相反,排序与聚合的顺序无关;然而,排序元素为下面将描述的框架选项赋予一定的含义,换句话说,排序元素帮助限定在窗口内的行。

2.3、框架

从本质上来说,框架是一个在分区内对行进行进一步限制的筛选器。它适用于聚合窗口函数,也适用于三个偏移函数:FIRST_VALUE、LAST_VALUE、NTH_VALUE。把这个窗口元素想成是基于给定的排序,在当前行所在分区中定义两个点,这两个点形成的框架之间的行才会参与计算。

在标准的框架描述中,包含一个ROWS或RANGE选项,用来定义框架的开始行和结束行,这两行也可以形成“框架外”(框架内的行被排除在计算外)窗口选项。SQL SERVER 2012 开始支持框架,完全实现ROWS选项,部分实现RANGE选项,尚未实现“框架外”窗口选项。

ROWS选项允许我们用相对当前行的偏移行数来指定框架的起点和终点。RANGE选项更具灵活性,可以以框架起终点的值于当前行的值的差异来定义偏移行数。“框架外”窗口选项用来定义如何对当前行及具有相同值的行进行处置。

 

3、支持窗口函数的查询元素

并不是所有的查询子句都支持窗口函数,相反,仅仅SELECT和ORDER BY 子句支持窗口函数。为帮助理解,我们先看看SQL不同子句的执行顺序:

1、FROM

2、WHERE

3、GROUP BY

4、HAVING

5、SELECT

 5.1、Evalute Expressions(判断表达式)

 5.2、删除重复数据

6、ORDER BY

7、OFFSET-FETCH/TOP

 

只有SELECT和ORDER BY 子句直接支持窗口函数。做这个限制的原因是为了避免二义性,因此把(几乎是)查询的最终结果当作窗口的起点。如果窗口函数可以早于SELECT阶段出现,那么通过一些查询表单会无法得到正确的结果。

 

4、窗口函数类别

窗口函数分为排名函数、分布函数、偏移函数等。

4.1、排名函数

SQL标准支持4种用于排名计算的窗口函数。它们是:ROW_NUMBER、NTILE、RANK和DENSE_RANK。在标准中,前两者是一类,后两者是另一类。

ROW_NUMBER函数根据指定的顺序,从1开始计算连续的行号。

NTILE函数把窗口分区里的数据行分成数量大致相等的块(根据输入的块数和指定的窗口排序)。

注意:为避免有人认为分块和分页相似,这里提醒大家,不要把二者混淆起来。在分页中,页的大小是常量,并且页码是动态的——查询结果集除以页面大小后得到的数值。而分开中,块的数量是常量,块的大小是动态的——行的数量除以设定的块的数量后得到的数值。分页在何处使用是很明显的,分块通常用于分析目的——那些需要涉及基于某种衡量顺序,把数据分到预先设定的固定数量、相同大小的桶(bucket)中。

RANK(排名)和DENSE_RANK(密集排名)函数的计算和ROW_NUMBER函数类似,唯一不同的是,它们在窗口分区内生成的值不必是唯一的。当窗口排序方向是升序时,RANK函数计算分区内排序值比当前行小的行的数量,在次数量上加1,就是当前行的排名;DENSE_RANK函数计算分区内相异的(distinct)排序值比当前行小的行的数量,在此数量上加1,就是当前行的排名。当窗口排序方向是降序时,RANK函数计算分区内排序属性比当前行大的行的数量,在此数量上加1,就是当前行的排名;DENSE_RANK函数计算分区内相异的(distinct)排序值比当前行大的行的数量,在此数量上加1,就是当前行的排名。

 

4.2、分布函数

窗口分布函数主要为静态统计服务提供数据的分布情况。SQL Server 2012引入了两种窗口分布函数的支持:排名分布函数和逆分布函数。排名分布函数有两种:PERCENT_RANK(百分位排名)和CUME_DIST(累积分布),逆分布函数也有两个:PERCENT_CONT(百分位连续)和PERCENTILE_DISC(百分位离散)。

根据标准SQL,分布函数计算数据行在窗口分区中的相对排名,把它表达成介于0~1之间的比值——我们大多数人把它看做百分比。

假设rk 为数据行的RANK值,RANK函数的窗口描述与分布函数的窗口描述相同。假设nr为窗口分区内数据行的行数。假设np为领先或与当前行的排序值相同的行的数目(为比当前rk减1大的最小rk值,如果当前的rk为最大值,np则等于nr)。

PERCENT_RANK(百分位排名)计算公式如下:(rk-1)/(nr-1),PERCENT_RANK(百分位排名)的计算公式如下:np/nr。

逆分布函数,通常叫百分位,我们可以把它执行的计算当作是排名分布函数的倒数。

PERCENTILE_DISC(百分位离散)函数(DISC为离散分布模型)返回组中第一个符合条件的值,条件是:其累计分布(CUME_DIST函数)大于等于输入值。

PERCENT_CONT(百分位连续)函数(CONT为连续分布函数)比较难理解(PERCENT_CONT(@pct) WITHIN GROUP(ORDER BY 分数))。举个简单示例,想象对一行数为偶数的组进行中值计算。我们需要内插值来支持连续分布假定,插入的值落在两个中间点的中间,意味着它是两个中间点的平均值。

 

4.3、偏移函数

窗口偏移函数包括两种类型的函数。一种是偏移量是相对于当前行的,这个类别的包括LAG和LEAD函数;另一个类别函数的偏移量是相对于窗口框架的开始和结尾的,这个类别包括FIRST_VALUE、LAST_VALUE和NTH_VALUE。第一类别中的函数(LAG和LEAD)支持窗口分区子句以及窗口排序子句。当然,后者的存在赋予偏移量以逻辑意义。第二类别中的函数(FIRST_VALUE、LAST_VALUE和NTH_VALUE)在支持窗口分区子句和排序子句的基础上,还支持窗口框架子句。

LAG和LEAD函数允许我们从窗口分区中,根据给定的相对于当前行的前偏移量(LAG)和后偏移量(LEAD),返回对应行的值。如果没有指定,偏移量默认为1。

FIRST_VALUE和FIRST_VALUE分别返回框架的第一行和最后一行所有查询的值。NTH_VALUE函数作用是中的相对窗口框架第一行或最后一行的偏移量,使得我们可以取得对应这个偏移量的记录值。

 

PS:1、最近看了关于SQL窗口函数也可作为T-SQL性能优化方案的相关书籍,于是整理了下相关概念。

         2、此篇提到的知识针对SQL SERVER  2012中有的窗口函数。

         3、此篇主要是为了整理窗口函数在T-SQL中的应用案例而做的准备工作。       

猜你喜欢

转载自blog.csdn.net/mzl87/article/details/84455076
今日推荐