1、概念理解
1.1 定义
窗口函数是应用于查询结果中一组行(称为“窗口”)的函数,允许用户在结果集中进行计算,并且能够保留每一行的原始数据。
核心特点:
- 不聚合结果集,保留行级数据
- 定义窗口,通过 OVER() 子句
常见的窗口函数:
-
排名类:
ROW_NUMBER(),RANK(),DENSE_RANK() -
分布类:
PERCENT_RANK(),CUME_DIST(),NTILE() -
前后值类:
LAG(),LEAD() -
头尾值类:
FIRST_VALUE(),LAST_VALUE() -
聚合函数 也可用作窗口函数:
SUM(),AVG(),COUNT(),MAX(),MIN()
1.2 与聚合函数的区别
定义:聚合函数是用于计算一组值并返回单个值的函数,通常与 GROUP BY 子句一起使用,将数据分组并计算每组的汇总结果。
| 特性 | 窗口函数 | 聚合函数 |
|---|---|---|
| 结果集 | 保留每一行的原始数据 | 返回分组后的单个汇总值 |
| 使用方式 | 使用 OVER 子句 | 通常与 GROUP BY 一起使用 |
| 计算范围 | 可以在整个数据集中或分区内计算 | 在分组后的每个组内计算 |
| 示例 | RANK() OVER (PARTITION BY department) | AVG(salary) GROUP BY department |
| 对 NULL 的处理 | 可自定义处理(如可选择包括或排除 NULL) | 通常忽略 NULL 值 |
1.3 OVER() 子句
OVER() 子句定义了窗口函数的“工作窗口”
PARTITION BY (分区):
-
作用:将整个结果集划分为更小的、独立的窗口或分区。窗口函数会分别应用于每个分区内部,并在跨分区边界时重置计算。
-
类比:相当于聚合函数中的
GROUP BY,但不对结果进行聚合。
ORDER BY (排序):
-
作用:在分区内部,定义行的逻辑顺序。
-
关键:对于许多窗口函数来说,
ORDER BY会隐式地定义窗口框架的范围
PARTITION BY和 ORDER BY可以单独或组合使用。
1.4 窗口范围:ROWS ... AND ...
当 OVER()子句中使用了 ORDER BY时,默认的窗口范围是:从分区的第一行到当前行。
可以通过 ROWS/RANGE BETWEEN 子句来 显式、精确地控制窗口的起始和结束边界。
关键词:
UNBOUNDED PRECEDING:分区的第一行。UNBOUNDED FOLLOWING:分区的最后一行。CURRENT ROW:当前行。N PRECEDING:当前行之前的第N行。N FOLLOWING:当前行之后的第N行。
ROWS VS RANGE:
ROWS:基于物理行的偏移
- 明确指定窗口的行数。
- 表示窗口中的行数是相对于当前行的位置来确定的。
- 适用于确切的行数计算,不考虑行的值。
RANGE:基于ORDER BY列值的逻辑偏移。
- 根据排序列的值来定义窗口,而不是具体的行数。
- 它表示窗口可以包括所有具有相同值的行。例如,
RANGE BETWEEN 100 PRECEDING AND CURRENT ROW表示当前行及其之前所有值不超过当前值 100 的行。 RANGE更加灵活,适用于需要考虑值范围的情况,但可能在处理相同值的行时导致窗口大小不固定。