
# 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);
```
