窗口函数 OVER 子句(Window Function)
窗口函数(Window Function/Windowing Function)在与当前行相关的一组行上执行计算(类似一个“窗口”框出一定范围的行)。
"窗口"是通过 OVER
子句定义的,通常包括三个部分:
- 窗口分区(
PARTITION BY
子句):指定如何将行分成更小的集合。 - 窗口排序(
ORDER BY
子句):指定行的排序方式。此部分对于排名函数是必需的。 - 窗口范围(
ROWS
子句):指定对哪一行或行的范围进行计算。
如果您的目标是在窗口关闭时仅生成仅追加输出的计算结果,可以利用窗口关闭时触发(emit-on-window-close)策略。这种方法有助于避免不必要的计算。有关该策略的更多信息,请参阅 窗口关闭时触发。
句法
window_function ( [expression [, expression ... ]] ) OVER
( PARTITION BY partition_expression
[ ORDER BY sort_expression [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] ]
[frame_clause])
目前,PARTITION BY
子句是必需的。如果您不想将行分成更小的集合,可以通过指定 PARTITION BY 1::int
来解决。
对于 row_number
和 rank
等排名窗口函数,ORDER BY
子句是必需的。
在流查询的 emit-on-window-close 模式下操作时,每个窗口函数都需要 ORDER BY
子句。请确保只指定一个列进行排序。这列通常是时间戳列,必须为其定义水位线。注意,当在另一个流查询中使用此流查询的时间戳列时,与该列关联的水位线信息不会保留。
window_function
可以是以下之一:
frame_clause
的句法是:
{ ROWS } frame_start [ frame_exclusion ]
{ ROWS } BETWEEN frame_start AND frame_end [ frame_exclusion ]
frame_start
和 frame_end
可以是:
UNBOUNDED PRECEDING
offset PRECEDING
CURRENT ROW
offset FOLLOWING
UNBOUNDED FOLLOWING
其中 offset
是正整数。如果只指定了 frame_start
,则 CURRENT ROW
将用作窗口的结束。
frame_exclusion
可以是以下之一:
EXCLUDE CURRENT ROW
EXCLUDE NO OTHERS
在 RisingWave 中,frame_clause
是可选的。根据是否存在 ORDER BY
子句,其默认值不同。当存在 ORDER BY
子句时,默认值是 ROWS UNBOUNDED PRECEDING AND CURRENT ROW
。当不存在 ORDER BY
子句时,默认值是 ROWS UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
。这与 PostgreSQL 中的行为不同。这种差异是暂时的。一旦 RisingWave 支持 RANGE
frame 子句,缺省值将与 PostgreSQL 保持一致。
通用窗口函数
row_number()
row_number()
函数为结果集的分区内的每一行分配一个唯一的连续整数。编号从每个分区的第一行开始为 1,并且对于每个后续行递增 1。
row_number()
可用于将非唯一行转换为唯一行。这可以用于消除重复行。
row_number()
的句法是:
row_number() → integer
我们建议仅在 top-N 模式查询中使用 row_number()
。有关此模式的详细信息,请参见 分组 Top-N。
rank()
rank()
返回当前行的排名,有间隔;即,它的同伴组中第一行的 row_number
。
rank()
的句法是:
rank() → integer
dense_rank()
dense_rank()
返回当前行的排名,无间隔;即,如果一些行共享相同的排名,则紧接它们的行被分配下一个连续的排名。
dense_rank()
的句法是:
dense_rank() → integer
lag()
和 lead()
lag()
允许您访问结果集中前一行的值。您可以指定向后查看的行数。
lag()
的句法是:
lag ( value anycompatible [, offset const integer] ) → anycompatible
lead()
类似于 lag()
,但它允许您访问结果集中后续行的值。
lead()
的句法是:
lead ( value anycompatible [, offset const integer] ) → anycompatible
first_value()
和 last_value()
first_value()
函数返回当前窗口框架中第一行的值。
first_value()
的句法是:
first_value ( value anyelement ) → anyelement
last_value()
返回当前窗口框架中最后一行的值。
last_value()
的句法是:
last_value ( value anyelement ) → anyelement
聚合窗口函数
聚合窗口函数包括 sum()
、min()
、max()
、avg()
和 count()
等。有关聚合函数的完整列表及其用法,请参见聚合函数。