计算机窗口函数是一种在数据集上执行计算的方法,它允许你在不改变数据行数的情况下,对数据集中的每一行添加一个新列,这个新列的值是基于当前行在某个“窗口”内的计算结果。窗口函数通常用于数据分析,比如排名、累计计算、动态分组等。
基本语法
```sql
function_name() OVER (
[PARTITION BY column_name]
[ORDER BY column_name]
[ROWS | RANGE BETWEEN frame_start AND frame_end]
)
```
`function_name`:要执行的窗口计算函数,如 `ROW_NUMBER()`、`RANK()`、`SUM()`、`AVG()` 等。
`PARTITION BY`:指定分组的列,窗口函数将在每个分组内独立执行。
`ORDER BY`:指定排序的列,用于确定窗口函数在分组内的排序方式。
`ROWS | RANGE`:指定窗口的大小和范围,`ROWS` 表示固定的行数范围,`RANGE` 表示基于当前行和指定偏移量的范围。
`frame_start` 和 `frame_end`:指定窗口的起始和结束行。
常见窗口函数
`ROW_NUMBER()`:为每一行分配一个唯一的数字,根据 `ORDER BY` 子句排序。
`RANK()`:为每一行分配一个排名,相同值的行将获得相同的排名。
`DENSE_RANK()`:类似于 `RANK()`,但不会跳过任何排名。
`SUM()`、`AVG()`、`MIN()`、`MAX()`:这些聚合函数也可以作为窗口函数使用,以便在每个窗口内进行计算。
`LEAD(col, n, DEFAULT)`:返回当前行的前一行或后一行的值。
`LAG(col, n, DEFAULT)`:返回当前行的前一行或后一行的值。
`FIRST_VALUE(col)`:返回窗口中的第一个值。
`LAST_VALUE(col)`:返回窗口中的最后一个值。
使用场景
分区排序:对数据进行分区,并在每个分区内进行排序。
动态 Group By:在不使用 `GROUP BY` 子句的情况下,对数据进行分组。
Top N:获取每个分组中的前 N 行数据。
累计计算:在每行上计算累计值,如累计销售额、累计用户数等。
层次查询:在查询结果中包含层次结构的数据。
示例
假设有一个销售数据表 `sales`,包含 `sale_date`(销售日期)和 `sales_amount`(销售额)列,我们可以使用窗口函数来计算每个产品在前几天的销售额:
```sql
SELECT
sale_date,
product_id,
sales_amount,
LAG(sales_amount) OVER (PARTITION BY product_id ORDER BY sale_date) AS previous_day_sales
FROM
sales;
```
在这个查询中,`LAG(sales_amount) OVER (PARTITION BY product_id ORDER BY sale_date)` 计算每个产品在前一天的销售金额。
注意事项
窗口子句必须和 `ORDER BY` 子句同时使用,且如果指定了 `ORDER BY` 子句未指定窗口子句,则默认为 `RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`。
当 `ORDER BY` 和窗口从句都缺失时,窗口规范默认是 `ROW BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`。
通过使用窗口函数,你可以更灵活地进行数据分析和报表统计,而无需进行复杂的聚合或排序操作。