且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

《T-SQL性能调优秘笈——基于SQL Server 2012 窗口函数》——1.3 窗口函数中的元素

更新时间:2022-10-13 20:30:49

本节书摘来自异步社区出版社《T-SQL性能调优秘笈——基于SQL Server 2012 窗口函数》一书中的第1章,第1.3节,作者: 【美】Itzik Ben-Gan,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.3 窗口函数中的元素

T-SQL性能调优秘笈——基于SQL Server 2012 窗口函数
窗口函数的行为描述出现在函数的OVER子句中,并涉及多个元素。3个核心元素是分区、排序和框架。不是所有的窗口函数都支持这3个元素。本节在介绍每个元素时会指出支持它的函数。

1.3.1 分区

分区元素由PARTITION BY子句定义,并被所有的窗口函数支持。它对当前计算的窗口进行限制,仅仅那些在结果集的分区列中与当前行有相同值的行才能进入窗口。例如,如果函数使用PARTITION BY custid,当前行的custid为1,那么对于当前行的窗口就是查询结果集中所有custid值为1的行。如果当前行的custid为2,那么对于当前行的窗口就是所有custid为2的行。

如果没有指定PARTITION BY子句,窗口就没有限制。换种说法就是:如果没有显式地指定分区,则默认分区就是把整个查询结果集当作一个分区。

有一点不太明显,这里提出来:同一个查询中的不同函数,可能会有不同的分区描述。把程序清单1-1内的查询当做一个示例:

程序清单1-1 查询中有两个RANK计算

《T-SQL性能调优秘笈——基于SQL Server 2012 窗口函数》——1.3 窗口函数中的元素

观察第一个RANK函数(它生成rnk_all列),它依赖默认分区,第二个RANK函数(它生成rnk_cust列)使用按照custid进行的显式分区。图1-4显示了在查询中,为3个示例计算结果定义的分区:一个rnk_all值和两个rnk_cust值。

《T-SQL性能调优秘笈——基于SQL Server 2012 窗口函数》——1.3 窗口函数中的元素

箭头从函数的结果值指向用于计算它们所属的窗口分区。

1.3.2 排序

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

有趣的是,针对不同的函数类别,排序元素有轻微的不同意义。对于排名函数,排序是直观的。例如,当使用降序排序时,RANK函数返回对应分区内大于当前值的记录的个数加1;当使用升序排序时,函数返回小于当前值的记录的个数加1。图1-5说明了之前列表1-1的排名情况——这次包含了对排序元素的解释。
《T-SQL性能调优秘笈——基于SQL Server 2012 窗口函数》——1.3 窗口函数中的元素

图1-5仅仅展示了在窗口中3行记录的排名计算。当然还有很多——准确地说,有1 660条。原因是有830行记录,对于每一行,都要计算两个排名(升序和降序)。从概念上来说,一个有趣的现象是这么多窗口时同时存在。

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

1.3.3 框架

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

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

ROWS选项允许我们用相对于当前行的偏移行数来指定框架的起点和终点。RANGE选项更具灵活性,可以以框架起终点的值与当前行的值的差异来定义偏移行数。“框架外”窗口选项用来定义如何对当前行及具有相同值的行进行处置,这样解释不够清晰和充分,但我暂时还不想深入到细节中去,后面会有更多的详述。目前,我只希望介绍概念,并提供一个简单的示例。下面是一个对EmpOrders视图的查询,计算每个员工每个订单月的销售数量累积总计:

我们观察到,窗口函数在qty特性上应用了SUM聚合窗口,用empid进行分区,分区中的行按照ordermonth进行排序,在分区内,按照给定的排序,设定框架为当前行之前的所有行(没有下边界点)。换句话说,结果合计的框架是当前行(包含)之前的所有行。这个查询的部分输出如下:

《T-SQL性能调优秘笈——基于SQL Server 2012 窗口函数》——1.3 窗口函数中的元素

可以看到,窗口的描述跟普通的英语一样简单。第2章提供框架选项的更多细节。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。