目录
[1️⃣ 排名类函数](#1️⃣ 排名类函数)
[2️⃣ 聚合类函数(不影响原始行)](#2️⃣ 聚合类函数(不影响原始行))
[3️⃣ 值访问函数](#3️⃣ 值访问函数)
[窗口范围说明(ROWS / RANGE)](#窗口范围说明(ROWS / RANGE))
什么是窗口函数?
窗口函数是一类 SQL 函数,在不分组的情况下,可以对查询结果中的某一"窗口"范围内的数据进行计算。
不同于聚合函数(如 SUM, AVG),窗口函数不会压缩行,而是为每一行返回一个计算值。
基本语法结构
sql
<窗口函数>([参数]) OVER (
[PARTITION BY 子句]
[ORDER BY 子句]
[ROWS 或 RANGE 子句]
)
-
PARTITION BY: 把数据分组,每组内独立执行函数(类似 GROUP BY,但不合并行)。 -
ORDER BY: 确定组内数据顺序。 -
ROWS BETWEEN: 精确控制窗口范围(例如:过去3行)。
举例:
sql
SELECT
department_id,
employee_id,
salary,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank_in_dept
FROM employees;
常见的窗口函数分类
1️⃣ 排名类函数
| 函数 | 描述 |
|---|---|
ROW_NUMBER() |
每一组数据中按顺序分配唯一行号 |
RANK() |
同分并列,跳跃排名(如:1,1,3) |
DENSE_RANK() |
同分不跳(如:1,1,2) |
NTILE(n) |
将结果分为 n 个桶,每行给出所属桶编号 |
1.ROW_NUMBER()
意义:按顺序为每行分配一个"唯一编号"。
名称:ROW_NUMBER = 行号。
语法示例:
sql
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS row_num
用途:
- 对每个部门中员工薪资进行唯一编号(常用于分页、去重等)
2.RANK()
意义:返回排名,相同值并列排名,后续名次跳跃。
名称:RANK = 排名。
语法示例:
sql
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank
| salary | RANK |
|---|---|
| 1000 | 1 |
| 1000 | 1 |
| 900 | 3 |
3.DENSE_RANK()
意义:与 RANK() 类似,但排名连续不跳跃。
名称:DENSE_RANK = 密集排名。
语法示例:
sql
DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS dense_rank
| salary | DENSE_RANK |
|---|---|
| 1000 | 1 |
| 1000 | 1 |
| 900 | 2 |
4. NTILE(n)
意义:将数据平均分成 n 个桶,每行返回桶编号。
名称:NTILE = "N Tile",即"分桶"。
语法示例:
sql
NTILE(4) OVER (ORDER BY salary DESC) AS quartile
用途:
- 按工资水平将员工划分为四个档次(四分位分析)
2️⃣ 聚合类函数(不影响原始行)
| 函数 | 描述 |
|---|---|
SUM(), AVG(), MAX(), MIN() |
聚合函数 + 窗口:在窗口范围内计算 |
COUNT() |
窗口内的行数统计 |
5. SUM(expr)、AVG(expr)、MAX(expr)、MIN(expr)
意义:在窗口内执行聚合计算,但不影响原始行展示。
名称:
-
SUM= 总和 -
AVG= 平均 -
MAX= 最大值 -
MIN= 最小值
语法示例:
sql
SUM(salary) OVER (PARTITION BY department_id ORDER BY hire_date) AS running_total
用途:
- 滚动汇总、组内对比等。
3️⃣ 值访问函数
| 函数 | 描述 |
|---|---|
LAG(expr, n, default) |
返回当前行前第 n 行的值 |
LEAD(expr, n, default) |
返回当前行后第 n 行的值 |
FIRST_VALUE(expr) |
窗口中的第一个值 |
LAST_VALUE(expr) |
窗口中的最后一个值 |
6. LAG(expr, offset, default)
意义:返回当前行的前 N 行的值。
名称:LAG = 滞后。
语法示例:
sql
LAG(salary, 1, 0) OVER (PARTITION BY department_id ORDER BY hire_date) AS prev_salary
用途:
- 分析趋势、比较环比。
7. LEAD(expr, offset, default)
意义:返回当前行的后 N 行的值。
名称:LEAD = 领先。
语法示例:
sql
LEAD(salary, 1, 0) OVER (PARTITION BY department_id ORDER BY hire_date) AS next_salary
用途:
- 预测未来、构建时间序列对比。
8. FIRST_VALUE(expr)
意义:返回窗口中按排序后第一行的值。
名称:FIRST_VALUE = 第一个值。
语法示例:
sql
FIRST_VALUE(salary) OVER (PARTITION BY department_id ORDER BY hire_date) AS first_salary
9. LAST_VALUE(expr)
意义:返回窗口中最后一行的值。
名称:LAST_VALUE = 最后一个值。
注意: LAST_VALUE 需要配合 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 才能获取整个分区最后一行值。
sql
LAST_VALUE(salary) OVER (
PARTITION BY department_id
ORDER BY hire_date
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) AS last_salary
窗口范围说明(ROWS / RANGE)
ROWS 是基于物理行号
sql
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
RANGE 是基于值范围
sql
RANGE BETWEEN INTERVAL 7 DAY PRECEDING AND CURRENT ROW
常见用途总结
| 场景 | 推荐函数 |
|---|---|
| 排名 | ROW_NUMBER, RANK, DENSE_RANK |
| 对比趋势 | LAG, LEAD, FIRST_VALUE, LAST_VALUE |
| 滚动汇总 | SUM, AVG, COUNT + ROWS BETWEEN |
| 分段统计 | NTILE |
| 时间窗口 | RANGE BETWEEN |