文档文档

SQL 窗口函数

窗口函数允许您计算运行总计、移动平均或其他类似聚合的结果,而无需将行折叠成组。它们在其计算范围内对行的“窗口”执行计算,您可以以各种方式对其进行分区和排序,并为集合中的每一行返回一个计算值。

与非窗口聚合函数(将每个组组合成单行)不同,窗口函数保留每一行的标识,并为分区中的每一行计算一个附加值。

例如,以下查询使用家庭传感器示例数据,并返回每个温度读数,以及查询时间范围内每个房间的平均温度

SELECT
  time,
  room,
  temp,
  avg(temp) OVER (PARTITION BY room) AS avg_room_temp
FROM
  home
WHERE
  time >= '2022-01-01T08:00:00Z'
  AND time <= '2022-01-01T09:00:00Z'
ORDER BY
  room,
  time
时间房间温度房间平均温度
2022-01-01T08:00:00厨房21.022.0
2022-01-01T09:00:00厨房23.022.0
2022-01-01T08:00:00客厅21.121.25
2022-01-01T09:00:00客厅21.421.25

窗口框架

由于窗口函数对行进行操作,因此在行的分区中有一组行,窗口函数使用该组行来执行操作。这组行称为窗口帧。窗口帧边界可以使用相对于当前行的 RANGEROWGROUPS 帧单位来定义 - 例如

SELECT
  time,
  temp,
  avg(temp) OVER (
    ORDER BY time
    RANGE INTERVAL '3 hours' PRECEDING
  ) AS 3h_moving_avg
FROM home
WHERE room = 'Kitchen'
SELECT
  time,
  temp,
  avg(temp) OVER (
    ROWS 3 PRECEDING
  ) AS moving_avg
FROM home
WHERE room = 'Kitchen'
SELECT
  time,
  room,
  temp,
  avg(temp) OVER (
    ORDER BY room
    GROUPS 1 PRECEDING
  ) AS moving_avg
FROM home

有关窗口帧如何工作的更多信息,请参阅 frame 子句

如果您未指定窗口帧,则窗口函数将使用当前分区中的所有行来执行其操作。

function([expr])
  OVER(
    [PARTITION BY expr[, ]]
    [ORDER BY expr [ ASC | DESC ][, ]]
    [ frame_clause ]
    )

OVER 子句

窗口函数使用直接跟随窗口函数的 OVER 子句
名称和参数。
OVER 子句在语法上区分窗口
函数与非窗口函数或聚合函数,并定义如何对行进行分组和排序以进行窗口操作。

PARTITION BY 子句

OVER 子句中的 PARTITION BY 子句将行划分为组或分区,这些组或分区共享 PARTITION BY 表达式的相同值。窗口函数对与当前行位于同一分区中的所有行进行操作。

ORDER BY 子句

OVER 子句内的 ORDER BY 子句控制窗口函数处理每个分区中行的顺序。当窗口子句包含 ORDER BY 子句时,窗口帧边界可以是显式的或隐式的,从而限制窗口帧大小在相对于当前行的两个方向上。

OVER 子句中的 ORDER BY 子句确定每个分区中行的处理顺序,并且与查询的 ORDER BY 子句分开。

Frame 子句

frame 子句定义窗口帧边界,可以是以下之一

{ RANGE | ROWS | GROUPS } frame_start
{ RANGE | ROWS | GROUPS } BETWEEN frame_start AND frame_end

Frame 单位

定义窗口帧时,可以使用以下帧单位之一

RANGE

使用在 ORDER BY 子句中指定的列的值,在相对于当前行值的value范围内定义帧边界。

使用 RANGE 帧单位时,必须包含一个带有仅一列ORDER BY 子句。

偏移量是当前行值与周围行值之间的差值。RANGE 支持以下偏移量类型

  • 数值(非负数)
  • 数值字符串(非负数)
  • 间隔

查看 RANGE 帧单位如何使用数值偏移量

查看 RANGE 帧单位如何使用间隔偏移量

ROWS

使用相对于当前行的行位置定义窗口帧边界。偏移量是与当前行的行位置的差值。ROWS 支持以下偏移量类型

  • 数值(非负数)
  • 数值字符串(非负数)

查看 ROWS 帧单位如何工作

GROUPS

使用行组定义窗口帧边界。对于 ORDER BY 子句中的列具有相同值的行,组成一个行组。

使用 GROUPS 帧单位时,请包含 ORDER BY 子句。

偏移量是相对于当前行组的行组位置的差值。GROUPS 支持以下偏移量类型

  • 数值(非负数)
  • 数值字符串(非负数)

查看 GROUPS 帧单位如何工作

Frame 边界

帧边界(frame_startframe_end)定义窗口函数在其上运行的每个帧的边界。

UNBOUNDED PRECEDING

从分区的首行开始,到当前行结束。

UNBOUNDED PRECEDING
offset PRECEDING

从当前行之前的 offset 帧单位开始,到当前行结束。例如,3 PRECEDING 包括当前行之前的 3 行。

<offset> PRECEDING
CURRENT ROW

用作边界时,在当前行开始和结束。

CURRENT ROW
offset FOLLOWING

从当前行开始,到当前行之后的 offset 帧单位结束。例如,3 FOLLOWING 包括当前行之后的 3 行。

<offset> FOLLOWING
UNBOUNDED FOLLOWING

从当前行开始,到分区的最后一行结束。

offset FOLLOWING

使用指定的 帧单位 偏移量当前行之后作为帧边界。

offset FOLLOWING
UNBOUNDED FOLLOWING

使用当前行到当前分区末尾的帧边界。

UNBOUNDED FOLLOWING

WINDOW 子句

使用 WINDOW 子句为窗口规范定义可重用的别名。当查询中的多个窗口函数共享相同的窗口定义时,这非常有用。

无需为每个函数重复相同的 OVER 子句,只需定义一次窗口并通过别名引用它 - 例如

SELECT
  sum(net_gain) OVER w,
  avg(net_net) OVER w
FROM
  finance
WINDOW w AS ( PARTITION BY ticker ORDER BY time DESC);

聚合函数

所有 聚合函数 都可以用作窗口函数。

排名函数

cume_dist

返回组中值的累积分布。返回的值大于 0 且小于或等于 1,并表示值在值集中的相对排名。ORDER BY 子句OVER 子句中用于正确计算当前行值的累积分布。

cume_dist()

使用 cume_dist 时,请在 OVER 子句中包含 ORDER BY 子句

查看 cume_dist 查询示例

dense_rank

返回当前行在其分区中的排名。排名是连续的;为重复值分配相同的排名编号,并且排名序列继续使用下一个不同的值(与 rank() 不同)。

ORDER BY 子句OVER 子句中确定排名顺序。

dense_rank()

查看 dense_rank 查询示例

比较 dense_rankrankrow_number 函数

ntile

将有序分区中的行分配到指定数量的组中。每个组都编号,从一开始。对于每一行,ntile 返回该行所属的组号。组号范围从 1 到 expression 值,尽可能均匀地划分分区。ORDER BY 子句OVER 子句中确定排名顺序。

ntile(expression)
参数
  • expression:整数。要将分区拆分成的组数。

查看 ntile 查询示例

percent_rank

返回当前行在其分区中的百分比排名。返回的值介于 01 之间,计算方式为

(rank - 1) / (total_rows - 1)

ORDER BY 子句OVER 子句中确定排名顺序。

percent_rank()

查看 percent_rank 查询示例

rank

返回当前行在其分区中的排名。对于重复值,rank 为它们分配相同的排名编号,跳过后续排名(与 dense_rank() 不同),然后继续使用下一个不同的值进行排名。

ORDER BY 子句OVER 子句中确定排名顺序。

rank()

查看 rank 查询示例

比较 dense_rankrankrow_number 函数

row_number

返回当前行在其分区中的位置,从 1 开始计数。ORDER BY 子句OVER 子句中确定行顺序。

row_number()

查看 row_number 查询示例

比较 dense_rankrankrow_number 函数

分析函数

first_value

从窗口帧的第一行返回值。

first_value(expression)
参数
  • expression:要操作的表达式。可以是常量、列或函数,以及算术运算符的任意组合。

last_value

查看 first_value 查询示例

lag

从分区中当前行之前指定偏移量的行返回值。如果偏移行在分区之外,则函数返回指定的默认值。

lag(expression, offset, default)
参数
  • expression:要操作的表达式。可以是常量、列或函数,以及算术或字符串运算符的任意组合。
  • offset:从当前行之前多少行检索 expression 的值。默认值为 1
  • default:如果偏移量在分区中,则返回的默认值。必须与 expression 的类型相同。

lead

查看 lag 查询示例

last_value

从窗口帧的最后一行返回值。

last_value(expression)
参数
  • expression:要操作的表达式。可以是常量、列或函数,以及算术运算符的任意组合。

first_value

查看 last_value 查询示例

lead

从分区中当前行之后指定偏移量的行返回值。如果偏移行在分区之外,则函数返回指定的默认值。

lead(expression, offset, default)
参数
  • expression:要操作的表达式。可以是常量、列或函数,以及算术或字符串运算符的任意组合。
  • offset:从当前行之前多少行检索 expression 的值。默认值为 1
  • default:如果偏移量在分区中,则返回的默认值。必须与 expression 的类型相同。

lag

查看 lead 查询示例

nth_value

从窗口帧的第 n 行返回值(从 1 开始计数)。如果第 n 行不存在,则函数返回 null

nth_value(expression, n)
参数
  • expression:要操作的表达式。可以是常量、列或函数,以及算术或字符串运算符的任意组合。
  • n:指定要引用的当前帧和分区中的行号。

查看 lead 查询示例


此页是否对您有帮助?

感谢您的反馈!


Flux 的未来

Flux 即将进入维护模式。您可以继续像现在一样使用它,而无需对代码进行任何更改。

阅读更多

现已全面上市

InfluxDB 3 Core 和 Enterprise

快速启动。更快扩展。

获取更新

InfluxDB 3 Core 是一个开源、高速、最近数据引擎,可实时收集和处理数据,并将其持久化到本地磁盘或对象存储。InfluxDB 3 Enterprise 构建在 Core 的基础上,增加了高可用性、读取副本、增强的安全性以及数据压缩,以实现更快的查询和优化的存储。InfluxDB 3 Enterprise 的免费层可供非商业家庭或业余爱好者使用。

有关更多信息,请查看