更新时间:2026-07-03 GMT+08:00
分享

OVER

功能描述

OVER子句与窗口函数配合使用,用于定义窗口的分区、排序和范围。窗口函数为每行数据基于其所在窗口计算一个值,而不像普通聚合函数那样将多行合并为一行。

语法格式

window_func ( [ expression [, ...] ] ) OVER
 ( [ PARTITION BY expression [, ...] ]
   [ ORDER BY expression [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] ]
   [ window_frame ] )

其中 window_frame 为:

{ ROWS | RANGE } BETWEEN frame_start AND frame_end 

frame_start 和 frame_end 为:

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

参数说明

参数

说明

window_func

窗口函数,包括聚合窗口函数(SUM、AVG、COUNT、MAX、MIN等)和排名窗口函数(RANK、DENSE_RANK、ROW_NUMBER、NTILE、LEAD、LAG、FIRST_VALUE、LAST_VALUE、NTH_VALUE等)。

PARTITION BY

按一个或多个表达式对数据进行分区,窗口函数在各分区内独立计算。类似于GROUP BY,但不合并行。

ORDER BY

决定窗口函数计算的顺序。可用ASC或DESC指定升序或降序。

ROWS

物理窗口,基于行号偏移定义窗口范围。

RANGE

逻辑窗口,基于ORDER BY表达式的值偏移定义窗口范围。

CURRENT ROW

当前行。

UNBOUNDED PRECEDING

窗口起点,从分区第一行开始。

UNBOUNDED FOLLOWING

窗口终点,到分区最后一行结束。

offset PRECEDING

从当前行向前偏移offset行(ROWS)或值(RANGE)。

offset FOLLOWING

从当前行向后偏移offset行(ROWS)或值(RANGE)。

NULLS FIRST

NULL值排在最前。

NULLS LAST

NULL值排在最后。

窗口范围示例

窗口范围

说明

ROWS BETWEEN CURRENT ROW AND CURRENT ROW

窗口只包含当前行

ROWS BETWEEN 3 PRECEDING AND 5 FOLLOWING

窗口从当前行向前3行到向后5行

ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW

窗口从分区开头到当前行(默认窗口)

ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING

窗口从当前行到分区结尾

ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING

窗口覆盖整个分区

ROWS与RANGE的区别

  • ROWS为物理窗口,根据行号偏移计算,与当前行的值无关。
  • RANGE为逻辑窗口,根据ORDER BY表达式的值偏移计算,包含值在范围内的所有行。

注意事项

  • OVER子句包括PARTITION BY、ORDER BY和窗口范围三部分,可组合使用。
  • 不指定ORDER BY时,窗口默认覆盖整个分区。
  • 不指定窗口范围时,默认窗口为ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW。
  • OVER子句为空时表示窗口为整张表。

示例

累计计数:

SELECT id, COUNT(id) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
   FROM over_test; 

分区排名:

SELECT name, class_id, score,
   RANK() OVER (PARTITION BY class_id ORDER BY score DESC) AS class_rank
   FROM student; 

移动平均:

SELECT date, amount,
   AVG(amount) OVER (ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
   FROM sales; 

使用窗口别名(Spark 4.0):

SELECT name, score,
   RANK() OVER w AS rnk,
   SUM(score) OVER w AS total
   FROM student
   WINDOW w AS (PARTITION BY class_id ORDER BY score DESC); 

相关文档