窗口函数
窗口函数对与当前行相关的一组行进行计算。与聚合函数不同,窗口函数不会把多行合并成单行——每一行都保留自己的输出结果。OVER 子句的完整语法(PARTITION BY、ORDER BY、window frame)见本页末尾的 OVER 子句章节。
| 函数 | 别名 | 说明 |
|---|---|---|
cume_dist |
— | 当前行的相对排名:(当前行之前或与之并列的行数)/(总行数) |
dense_rank |
— | 返回当前行的排名,排名之间无间隔 |
ntile |
— | 把分区尽可能均匀地划分为指定数量的组,返回 1 到组数之间的整数 |
percent_rank |
— | 返回当前行在其分区内的百分比排名,取值范围 0 到 1 |
rank |
— | 返回当前行在其分区内的排名,排名之间允许有间隔 |
row_number |
— | 当前行在其分区内的行号,从 1 开始计数 |
lag |
— | 返回分区内当前行之前第 offset 行处表达式的值 |
lead |
— | 返回分区内当前行之后第 offset 行处表达式的值 |
排名函数
cume_dist
当前行的相对排名:(当前行之前或与之并列的行数)/(总行数)。
语法:cume_dist()
示例:
1> SELECT x, cume_dist() OVER (ORDER BY x) AS cume_dist FROM (VALUES (1), (1), (2), (3)) AS t(x);
2+---+-----------+
3| x | cume_dist |
4+---+-----------+
5| 1 | 0.5 |
6| 1 | 0.5 |
7| 2 | 0.75 |
8| 3 | 1.0 |
9+---+-----------+
dense_rank
返回当前行的排名,排名之间无间隔。该函数以稠密方式对行排名,即使遇到相同的值,也会分配连续的排名。
语法:dense_rank()
示例:
1> SELECT x, dense_rank() OVER (ORDER BY x) AS dense_rank FROM (VALUES (1), (1), (2), (3)) AS t(x);
2+---+------------+
3| x | dense_rank |
4+---+------------+
5| 1 | 1 |
6| 1 | 1 |
7| 2 | 2 |
8| 3 | 3 |
9+---+------------+
ntile
返回 1 到参数值之间的整数,把分区尽可能均匀地划分为若干组。
语法:ntile(expression)
参数:
- expression:一个整数,表示分区应被划分成的组数
示例:
1> SELECT x, ntile(2) OVER (ORDER BY x) AS bucket FROM (VALUES (1), (2), (3), (4)) AS t(x);
2+---+--------+
3| x | bucket |
4+---+--------+
5| 1 | 1 |
6| 2 | 1 |
7| 3 | 2 |
8| 4 | 2 |
9+---+--------+
percent_rank
返回当前行在其分区内的百分比排名。取值范围为 0 到 1,按 (rank - 1) / (total_rows - 1) 计算。
语法:percent_rank()
示例:
1> SELECT x, percent_rank() OVER (ORDER BY x) AS percent_rank FROM (VALUES (1), (1), (2), (3)) AS t(x);
2+---+--------------------+
3| x | percent_rank |
4+---+--------------------+
5| 1 | 0.0 |
6| 1 | 0.0 |
7| 2 | 0.6666666666666666 |
8| 3 | 1.0 |
9+---+--------------------+
rank
返回当前行在其分区内的排名,排名之间允许有间隔。该函数提供与 row_number 类似的排名,但遇到相同的值时会跳过后续排名。
语法:rank()
示例:
1> SELECT x, rank() OVER (ORDER BY x) AS rank FROM (VALUES (1), (1), (2), (3)) AS t(x);
2+---+------+
3| x | rank |
4+---+------+
5| 1 | 1 |
6| 1 | 1 |
7| 2 | 3 |
8| 3 | 4 |
9+---+------+
row_number
当前行在其分区内的行号,从 1 开始计数。
语法:row_number()
示例:
1> SELECT x, row_number() OVER (ORDER BY x) AS row_num FROM (VALUES ('a'), ('b'), ('c')) AS t(x);
2+---+---------+
3| x | row_num |
4+---+---------+
5| a | 1 |
6| b | 2 |
7| c | 3 |
8+---+---------+
分析函数
lag
返回分区内当前行之前第 offset 行处表达式求值的结果;如果不存在这样的行,则返回 default(其类型必须与表达式的值相同)。
语法:lag(expression[, offset[, default]])
参数:
- expression:要操作的表达式
- offset:整数。指定向前回溯多少行来获取 expression 的值。默认为 1。
- default:offset 超出分区范围时返回的默认值。类型必须与 expression 相同。
示例:
1> SELECT x, lag(x) OVER (ORDER BY x) AS prev_x FROM (VALUES (10), (20), (30)) AS t(x);
2+----+--------+
3| x | prev_x |
4+----+--------+
5| 10 | |
6| 20 | 10 |
7| 30 | 20 |
8+----+--------+
lead
返回分区内当前行之后第 offset 行处表达式求值的结果;如果不存在这样的行,则返回 default(其类型必须与表达式的值相同)。
语法:lead(expression[, offset[, default]])
参数:
- expression:要操作的表达式
- offset:整数。向后偏移多少行(取当前行之后第 offset 行)来获取 expression 的值。默认为 1。
- default:offset 超出分区范围时返回的默认值。类型必须与 expression 相同。
示例:
1> SELECT x, lead(x) OVER (ORDER BY x) AS next_x FROM (VALUES (10), (20), (30)) AS t(x);
2+----+--------+
3| x | next_x |
4+----+--------+
5| 10 | 20 |
6| 20 | 30 |
7| 30 | |
8+----+--------+
OVER 子句
窗口函数(以及任意聚合函数)通过 OVER 子句定义计算窗口:
1function([expression]) OVER (
2 [PARTITION BY expression[, ...]]
3 [ORDER BY expression [ASC | DESC][, ...]]
4 [frame]
5)
PARTITION BY:按表达式把行分成互不影响的分区,窗口计算在分区内进行;时序场景通常按 tag 列分区,让每个序列独立计算。ORDER BY:分区内的行序,排名函数与lag/lead依赖它。frame:窗口帧,形如{ROWS | RANGE | GROUPS} BETWEEN frame_start AND frame_end,限定聚合参与的行范围;边界可用UNBOUNDED PRECEDING、n PRECEDING、CURRENT ROW、n FOLLOWING、UNBOUNDED FOLLOWING。
典型用法——按序列分区的滑动平均(窗口为当前点与前一点):
1> SELECT time, room, temp, avg(temp) OVER (PARTITION BY room ORDER BY time ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS moving_avg FROM temps ORDER BY room, time;
2+---------------------+---------+------+------------+
3| time | room | temp | moving_avg |
4+---------------------+---------+------+------------+
5| 2024-01-01T00:00:00 | kitchen | 20.0 | 20.0 |
6| 2024-01-01T00:01:00 | kitchen | 22.5 | 21.25 |
7| 2024-01-01T00:02:00 | kitchen | 24.5 | 23.5 |
8| 2024-01-01T00:00:00 | living | 21.0 | 21.0 |
9| 2024-01-01T00:01:00 | living | 21.5 | 21.25 |
10| 2024-01-01T00:02:00 | living | 23.0 | 22.25 |
11+---------------------+---------+------+------------+
评价此篇文章
