SQL窗口函数用法
窗口函数是一种在关系型数据库中执行聚合、排序和分析操作的强大工具。它们在处理查询结果时提供了更多灵活性和控制力,使得可以在特定数据集的子集上执行计算,而不会改变查询结果的行数。
窗口函数语法
窗口函数应用于SELECT子句,语法结构如下:
1 | window_function (expression) OVER ( |
其中各项含义如下:
- partition by:将数据按给出的字段进行数据分区。不指定这一部分时,将所有数据作为同一分区。
- order by:将各分区内的数据按给出的条件进行排序。
- { rows | range } between frame start and frame_end:基于分区内的数据为每一行生成一个frame,大部分窗口函数将在frame上执行。不指定这一部分时,根据是否有order by部分,采用不同的默认值。没有order by部分时,相当于rows between unbounded preceding and unbounded following,取得分区内的所有值。有order by部分时,相当于rows between unbounded preceding and current row,取得分区内第一行数据到当前行的范围。rows和range两种范围分别表示基于行来筛选frame、基于值的范围来筛选frame。
- window_function:对frame内的数据进行处理,执行聚合、取值、排序等功能,生成数据附加到当前行上。但row_number()、rank()等部分窗口函数只会应用在分区上。
在SQL的逻辑执行顺序上,其位于SELECT之后,ORDER BY之前。
可用的窗口函数
支持的聚合函数:SUM();COUNT();AVG();MIN();MAX()。
支持的取值函数:FIRST_VALUE (expression)取第一行的值;LAST_VALUE (expression)取最后一行的值;LAG (expression [, offset [, default_value]])取当前行前offset行的值并在无法取得值时使用default_value作为默认值;LEAD (expression [, offset [, default_value]])取当前行后offset行的值并在无法取得值时使用default_value作为默认值。
支持的排序函数:CUME_DIST()计算当前行的累计分布比例,值的最终范围为(0,1];PERCENT_RANK()计算当前行的百分比排名,值的最终范围为[0,1];DENSE_RANK()计算当前行的密集排名(相同值也使用不同的排名,不支持并列);RANK()计算当前行的排名(支持并列,比如2人并列第1,下一个就是第3);NTILE(num_buckets)将数据平均分为num_buckets个桶(最后一个桶可能不够)并给出桶号;ROW_NUMBER()计算当前行在分区中的位置,从1开始。
需要注意的是,lag()、lead()、row_number()、ntile()、rank()、dense_rank()、percent_rank()、cume_dist()都直接在分区范围上工作,而不是在frame上。
窗口函数示例
在MySQL、PostgreSQL、SQL Server中都支持这些窗口函数,下面的示例在3种数据库中都能正常工作。
1 | drop table if exists students; |
执行结果如下:
1 | +----------+-----+-----+-------+-------+-----+-----+-------------+------------+-----+------+------------+-------+------+------------+-------------------+-----------+ |