跳转到主要内容
窗口函数可让你对与当前行相关的一组行进行计算。 其中有些计算与聚合函数所能完成的计算类似,但窗口函数不会将多行分组成单个输出,仍会返回各个行。

标准窗口函数

ClickHouse 支持定义窗口和窗口函数的标准语法。下表列出了当前各项功能的支持情况。

ClickHouse 特有的窗口函数

以下是 ClickHouse 特有的窗口函数:

nonNegativeDerivative(metric_column, timestamp_column[, INTERVAL X UNITS])

根据 timestamp_column 计算给定 metric_column 的非负导数。 INTERVAL 可省略,默认为 INTERVAL 1 SECOND。 各行的计算值如下:
  • 第 1 行为 0
  • ii 行为 metricimetrici1timestampitimestampi1interval{\text{metric}_i - \text{metric}_{i-1} \over \text{timestamp}_i - \text{timestamp}_{i-1}} * \text{interval}

语法

  • PARTITION BY - 定义如何将结果集划分为多个组。
  • ORDER BY - 定义在计算 aggregate_function 时,如何对组内的行进行排序。
  • ROWS or RANGE - 定义窗口帧的边界,aggregate_function 在窗口帧内进行计算。
  • WINDOW - 允许多个表达式使用同一个窗口定义。

函数

这些函数只能用作窗口函数。
  • row_number() - 对当前行在其分区内从 1 开始编号。
  • first_value(x) - 返回其有序窗口帧内计算得到的第一个值。
  • last_value(x) - 返回其有序窗口帧内计算得到的最后一个值。
  • nth_value(x, offset) - 返回其有序窗口帧中第 n 行 (offset) 计算得到的第一个非 NULL 值。
  • rank() - 对当前行在其分区内进行有间隔排名。
  • dense_rank() - 对当前行在其分区内进行无间隔排名。
  • lagInFrame(x) - 返回其有序窗口帧内当前行之前按指定物理偏移量对应行上计算得到的值。
  • leadInFrame(x) - 返回其有序窗口帧内当前行之后偏移若干行处计算得到的值。

示例

下面来看一些窗口函数的使用示例。

为行编号

聚合函数

将每位球员的薪资与其所在球队的平均薪资进行比较。
比较每位球员的薪资与其所在球队的最高薪资。

按列分区

窗口帧边界

┌─part_key─┬─value─┬─order─┬─frame_values─┬─rn_1─┬─rn_2─┬─rn_3─┬─rn_4─┐ │ 1 │ 1 │ 1 │ [5,4,3,2,1] │ 5 │ 5 │ 5 │ 2 │ │ 1 │ 2 │ 2 │ [5,4,3,2] │ 4 │ 4 │ 4 │ 2 │ │ 1 │ 3 │ 3 │ [5,4,3] │ 3 │ 3 │ 3 │ 2 │ │ 1 │ 4 │ 4 │ [5,4] │ 2 │ 2 │ 2 │ 2 │ │ 1 │ 5 │ 5 │ [5] │ 1 │ 1 │ 1 │ 1 │ └──────────┴───────┴───────┴──────────────┴──────┴──────┴──────┴──────┘
┌─frame_values_1─┬─second_value─┐ │ [1] │ ᴺᵁᴸᴸ │ │ [1,2] │ 2 │ │ [1,2,3] │ 2 │ │ [1,2,3,4] │ 2 │ │ [2,3,4,5] │ 3 │ └────────────────┴──────────────┘

真实场景示例

以下示例用于解决常见的实际问题。

各部门的最高/总工资

累积和

移动平均 / 滑动平均 (每 3 行)

insert into sensors values(‘cpu_temp’, ‘2020-01-01 00:00:00’, 87), (‘cpu_temp’, ‘2020-01-01 00:00:01’, 77), (‘cpu_temp’, ‘2020-01-01 00:00:02’, 93), (‘cpu_temp’, ‘2020-01-01 00:00:03’, 87), (‘cpu_temp’, ‘2020-01-01 00:00:04’, 87), (‘cpu_temp’, ‘2020-01-01 00:00:05’, 87), (‘cpu_temp’, ‘2020-01-01 00:00:06’, 87), (‘cpu_temp’, ‘2020-01-01 00:00:07’, 87);

移动平均 / 滑动平均 (每 10 秒)

移动平均 / 滑动平均 (每 10 天)

温度以秒级精度存储,但通过使用 RangeORDER BY toDate(ts),我们构造了一个大小为 10 个单位的窗口帧;而由于使用了 toDate(ts),这里的单位就是天。
insert into sensors values(‘ambient_temp’, ‘2020-01-01 00:00:00’, 16), (‘ambient_temp’, ‘2020-01-01 12:00:00’, 16), (‘ambient_temp’, ‘2020-01-02 11:00:00’, 9), (‘ambient_temp’, ‘2020-01-02 12:00:00’, 9), (‘ambient_temp’, ‘2020-02-01 10:00:00’, 10), (‘ambient_temp’, ‘2020-02-01 12:00:00’, 10), (‘ambient_temp’, ‘2020-02-10 12:00:00’, 12), (‘ambient_temp’, ‘2020-02-10 13:00:00’, 12), (‘ambient_temp’, ‘2020-02-20 12:00:01’, 16), (‘ambient_temp’, ‘2020-03-01 12:00:00’, 16), (‘ambient_temp’, ‘2020-03-01 12:00:00’, 16), (‘ambient_temp’, ‘2020-03-01 12:00:00’, 16);

参考资料

GitHub Issues

有关窗口函数初步支持的路线图,请参见此 issue 所有与窗口函数相关的 GitHub issue 都带有 comp-window-functions 标签。

测试

这些测试包含当前已支持语法的示例: https://github.com/ClickHouse/ClickHouse/blob/master/tests/performance/window_functions.xml https://github.com/ClickHouse/ClickHouse/blob/master/tests/queries/0_stateless/01591_window_functions.sql

Postgres 文档

https://www.postgresql.org/docs/current/sql-select.html#SQL-WINDOW https://www.postgresql.org/docs/devel/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS https://www.postgresql.org/docs/devel/functions-window.html https://www.postgresql.org/docs/devel/tutorial-window.html

MySQL 文档

https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html https://dev.mysql.com/doc/refman/8.0/en/window-functions-usage.html https://dev.mysql.com/doc/refman/8.0/en/window-functions-frames.html
最后修改于 2026年6月19日