窗口函数 - AWS Clean Rooms

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

窗口函数

通过使用窗口函数,您可以更高效地创建分析业务查询。窗口函数运行于分区或结果集的“窗口”上,并为该窗口中的每个行返回一个值。相比之下,非窗口函数执行与结果集中的每个行相关的计算。与聚合结果行的分组函数不同,窗口函数在表的表达式中的保留所有行。

使用该窗口中的行集中的值计算返回的值。对于表中的每一行,窗口定义一组用于计算其他属性的行。窗口是使用窗口规范(OVER子句)定义的,它基于三个主要概念:

  • 窗口分区,它形成行组(PARTITION子句)

  • 窗口排序,定义每个分区内的行顺序或顺序(BY 子ORDER句)

  • 窗口框架,相对于每行进行定义,以进一步限制行集(ROWS规范)

窗口函数是查询中除最后一个 BY 子句之外的最后ORDER一组操作。在处理窗口函数之前WHERE,GROUP所有联接以及所有、B HAVING Y 和子句都已完成。因此,窗口函数只能出现在选择列表或 B ORDER Y 子句中。您可以在一个具有不同框架子句的查询中使用多个窗口函数。也可以在其他标量表达式中使用窗口函数,例如CASE。

窗口函数语法摘要

窗口函数遵循标准语法,如下所示。

function (expression) OVER ( [ PARTITION BY expr_list ] [ ORDER BY order_list [ frame_clause ] ] )

其中,function 是本部分介绍的函数之一。

expr_list 如下所示。

expression | column_name [, expr_list ]

order_list 如下所示。

expression | column_name [ ASC | DESC ] [ NULLS FIRST | NULLS LAST ] [, order_list ]

frame_clause 如下所示。

ROWS { UNBOUNDED PRECEDING | unsigned_value PRECEDING | CURRENT ROW } | { BETWEEN { UNBOUNDED PRECEDING | unsigned_value { PRECEDING | FOLLOWING } | CURRENT ROW} AND { UNBOUNDED FOLLOWING | unsigned_value { PRECEDING | FOLLOWING } | CURRENT ROW }}

参数

函数

窗口函数。有关详细信息,请参阅各个函数描述。

OVER

定义窗口规范的子句。该OVER子句对于窗口函数是必需的,它将窗口函数与其他SQL函数区分开来。

PARTITION按 expr_list

(可选)B PARTITION Y 子句将结果集细分为多个分区,与 BY 子句非常相似。GROUP如果存在分区子句,则为每个分区中的行计算该函数。如果未指定任何分区子句,则一个分区包含整个表,并为整个表计算该函数。

排名函数 DENSE _ RANK、NTILERANK、和 ROW _ NUMBER 需要对结果集中的所有行进行全局比较。使用 BY 子句时,查询优化器可以通过根据分区将工作负载分散到多个切片来并行运行每个聚合。PARTITION如果不存在 BY 子PARTITION句,则聚合步骤必须在单个切片上连续运行,这可能会对性能产生严重的负面影响,尤其是对于大型集群。

AWS Clean Rooms 不支持 BY 子句中的PARTITION字符串文字。

ORDER按订单列表排序

(可选)窗口函数应用于每个分区中ORDER按照 BY 中的顺序规范排序的行。此 B ORDER Y 子句与 fr ame_c lause 中的 ORDER BY 子句截然不同,并且完全无关。B ORDER Y 子句可以在不使用 B PARTITION Y 子句的情况下使用。

对于排名函数,B ORDER Y 子句用于标识排名值的度量。对于聚合函数,分区的行必须在为每个框架计算聚合函数之前进行排序。有关窗口函数的更多信息,请参阅 窗口函数

顺序列表中需要列标识符或计算结果为列标识符的表达式。常数和常数表达式都不可用作列名称的替代。

NULLS值被视为自己的组,根据NULLSFIRST或NULLSLAST选项进行排序和排名。默认情况下,NULL值按ASC顺序排序并排在最后,按顺序排序并排在DESC第一位。

AWS Clean Rooms 不支持 BY 子句中的ORDER字符串文字。

如果省略 BY 子ORDER句,则行的顺序是不确定的。

注意

在任何并行系统中 AWS Clean Rooms,例如,当 B ORDER Y 子句不生成数据的唯一和总体顺序时,行的顺序是不确定的。也就是说,如果 B ORDER Y 表达式生成重复的值(部分排序),则这些行的返回顺序可能因运行而异。 AWS Clean Rooms 反过来,窗口函数可能返回意外的或不一致的结果。有关更多信息,请参阅 窗口函数的唯一数据排序

column_name

执行分区或排序操作所依据的列的名称。

ASC | DESC

一个定义表达式的排序顺序的选项,如下所示:

  • ASC: 升序(例如,对于数值,从低到高,对于字符串,从 “A” 到 “Z”)。如果未指定选项,则默认情况下将按升序对数据进行排序。

  • DESC: 降序(对于数值,从高到低;对于字符串,“Z” 到 “A”)。

NULLS FIRST | NULLS LAST

该选项指定NULLS应在非空值之前排序,还是应在非空值之后排在最后。默认情况下,NULLS按ASC顺序排序并排在最后,在排序中排序并排在DESC第一位。

frame_clause

对于聚合函数,使用 ORDER BY 时,frame 子句会进一步细化函数窗口中的行集。它使您可以包含或排除已排序结果中的行集。frame 子句由ROWS关键字和关联的说明符组成。

frame 子句不适用于排名函数。此外,如果聚合函数的子句中未使用 BY 子ORDER句,则不需要使用 frame OVER 子句。如果聚合函数使用 BY 子ORDER句,则需要显式框架子句。

如果未指定 BY 子ORDER句,则隐含的框架是无界限的,等同于。ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING

ROWS

此子句通过从当前行中指定物理偏移来定义窗口框架。

此子句指定当前行中的值将并入的当前窗口或分区中的行。它使用指定行位置的参数,行位置可位于当前行之前或之后。所有窗口框架的参考点为当前行。当窗口框架向前滑向分区中时,每个行会依次成为当前行。

框架可以是一组超过并包括当前行的行。

{UNBOUNDED PRECEDING | offset PRECEDING | CURRENT ROW}

或者可以是两个边界之间的一组行。

BETWEEN { UNBOUNDED PRECEDING | offset { PRECEDING | FOLLOWING } | CURRENT ROW } AND { UNBOUNDED FOLLOWING | offset { PRECEDING | FOLLOWING } | CURRENT ROW }

UNBOUNDEDPRECEDING表示窗口从分区的第一行开始;o ffset PRECEDING 表示窗口启动的行数等于当前行之前的 offset 值。 UNBOUNDEDPRECEDING是默认值。

CURRENTROW表示窗口在当前行开始或结束。

UNBOUNDEDFOLLOWING表示窗口在分区的最后一行结束;offse t FOLLOWING 表示窗口结束的行数等于当前行之后的偏移量值。

offset 标识当前行之前或之后的实际行数。在这种情况下,offset 必须为计算结果为正数值的常数。例如,5 在当前行之后五行FOLLOWING结束帧。

如果BETWEEN未指定,则框架以当前行为隐式边界。例如,ROWS 5 PRECEDING 等于 ROWS BETWEEN 5 PRECEDING AND CURRENT ROW。同时,ROWS UNBOUNDED FOLLOWING 等于 ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING

注意

您无法指定起始边界大于结束边界的框架。例如,您无法指定以下任一框架。

between 5 following and 5 preceding between current row and 2 preceding between 3 following and current row

窗口函数的唯一数据排序

如果窗口函数ORDER的 BY 子句不能生成数据的唯一和总顺序,则行的顺序是不确定的。如果 ORDER BY 表达式生成重复的值(部分排序),则这些行的返回顺序在多次运行中可能会有所不同。在这种情况下,窗口函数还可能返回意外的或不一致的结果。

例如,以下查询在多次运行中返回了不同的结果。之所以出现这些不同的结果,是因为order by dateid不会为SUM窗口函数生成唯一的数据顺序。

select dateid, pricepaid, sum(pricepaid) over(order by dateid rows unbounded preceding) as sumpaid from sales group by dateid, pricepaid; dateid | pricepaid | sumpaid --------+-----------+------------- 1827 | 1730.00 | 1730.00 1827 | 708.00 | 2438.00 1827 | 234.00 | 2672.00 ... select dateid, pricepaid, sum(pricepaid) over(order by dateid rows unbounded preceding) as sumpaid from sales group by dateid, pricepaid; dateid | pricepaid | sumpaid --------+-----------+------------- 1827 | 234.00 | 234.00 1827 | 472.00 | 706.00 1827 | 347.00 | 1053.00 ...

在这种情况下,在窗口函数中添加第二个 ORDER BY 列可以解决问题。

select dateid, pricepaid, sum(pricepaid) over(order by dateid, pricepaid rows unbounded preceding) as sumpaid from sales group by dateid, pricepaid; dateid | pricepaid | sumpaid --------+-----------+--------- 1827 | 234.00 | 234.00 1827 | 337.00 | 571.00 1827 | 347.00 | 918.00 ...

支持的函数

AWS Clean Rooms 支持两种类型的窗口函数:聚合和排名。

以下是支持的聚合函数:

以下是支持的排名函数:

窗口函数示例的示例表

您可以通过每个函数描述找到特定的窗口函数示例。其中一些示例使用名为的表WINSALES,该表包含 11 行,如下表所示。

SALESID DATEID SELLERID BUYERID QTY QTY_SHIPPED
30001 8/2/2003 3 B 10 10
10001 12/24/2003 1 C 10 10
10005 12/24/2003 1 A 30
40001 1/9/2004 4 A 40
10006 1/18/2004 1 C 10
20001 2/12/2004 2 B 20 20
40005 2/12/2004 4 A 10 10
20002 2/16/2004 2 C 20 20
30003 4/18/2004 3 B 15
30004 4/18/2004 3 B 20
30007 9/7/2004 3 C 30