可以对窗口函数之后再加条件_数据分析|SQL窗口函数最全使用指南

可以对窗口函数之后再加条件_数据分析|SQL窗口函数最全使用指南_第1张图片

一、why?为什么要使用窗口函数

在日常工作中经常会遇到类似这样的需求:

怎么样得到各部门工资排名前N名的员工列表?
查找各部门每人工资占部门总工资的百分比?

对于这样的需求,使用传统的SQL实现起来比较困难,这类需求都有一个共同的特点,需要在单表中满足某些条件的记录集内部做一些函数操作。不使用窗口函数的话可能要进行多次的表连接操作,可读性差的同时还会影响性能。

二、what?什么是窗口函数

窗口函数也称为OLAP(Online Anallytical Processing)函数,意思是对数据库数据进行实时分析处理。窗口函数就是为了实现OLAP而添加的标准SQL功能。

什么叫窗口?

窗口的概念非常重要,它可以理解为记录集合,窗口函数也就是在满足某种条件的记录集合上执行的特殊函数,对于每条记录都要在此窗口内执行函数,有的函数,随着记录不同,窗口大小都是固定的,这种属于静态窗口;有的函数则相反,不同的记录对应着不同的窗口,这种动态变化的窗口叫滑动窗口。

窗口函数和普通聚合函数也很容易混淆,二者区别如下:

  • 聚合函数是将多条记录聚合为一条;而窗口函数是每条记录都会执行,查询结果并不会改变记录条数,有几条记录执行完还是几条。
  • 普通聚合函数也可以用于窗口函数中,赋予它窗口函数的功能。

原因就在于窗口函数的执行顺序(逻辑上的)是在FROM,JOIN,WHERE,GROUP BY,HAVING之后,在ORDER BY,LIMIT,SELECT DISTINCT之前。它执行时GROUP BY的聚合过程已经完成了,所以不会再产生数据聚合。

窗口函数的简单语法如下:

<

举个例子,比如现在有一张学生成绩表student,分别有学生姓名s_name,课程名称c_name和课程成绩score三个字段,有个需求是“给出所有学生每门课的成绩排名”,这个需求可以用序号窗口函数轻松解决,伪代码如下:

<

那么<窗口函数>还有哪些呢?

  1. 一些专用的窗口函数,随后会举例介绍其用法功能
  • 序号函数:row_number() / rank() / dense_rank()
  • 分布函数:percent_rank() / cume_dist()
  • 前后函数:lag() / lead()
  • 头尾函数:first_val() / last_val()
  • 其他函数:nth_value() / 用途:将分区中的有序数据分为n个桶,记录桶号。

2. 原有的聚合函数也可用作窗口函数,如下

  • sum(),avg(),count(),max(),min()

三、how?窗口函数如何使用

这里使用经典的学生-课程-成绩结构,表架构如下:

student(sid, sname, sclass) ——学生表(学生ID,学生姓名,学生班级)
course(cid, cname) ——课程表(课程ID,课程名称)
score(sid, cid, score) ——成绩表 (学生ID,课程ID,成绩)

之后的例子主要是为了介绍函数功能,有些例子可能不太合适哈哈哈哈

  1. 序号函数
  • row_number() 、 rank() 、 dense_rank()都是序号函数,可以通过如下例子了解它们的区别
SELECT 

结果如下:

可以对窗口函数之后再加条件_数据分析|SQL窗口函数最全使用指南_第2张图片

可以发现,ROW_NUMBER()函数可以理解为排序号,不考虑并列;RANK()函数也为排号,考虑并列,并列之后的按照实际序号来;ROW_NUMBER()同样是排号,考虑并列,并列之后按下一个名次来。

2.分布函数

percent_rank()

  • 用途:和之前的RANK()函数相关,每行按照如下公式进行计算:
(rank - 1) / (rows - 1)

其中,rank为RANK()函数产生的序号,rows为当前窗口的记录总行数。

SELECT 

可以对窗口函数之后再加条件_数据分析|SQL窗口函数最全使用指南_第3张图片

cume_dist()

  • 用途:分组内大于等于当前rank值的行数/分组内总行数,这个函数比percen_rank使用场景更多。
  • 应用场景:班级中比当前同学成绩高的学生比例是多少
SELECT 

可以对窗口函数之后再加条件_数据分析|SQL窗口函数最全使用指南_第4张图片

其中关羽的北冥神功课考了100分,在这门课程中大于等于100分的比例为10%,也就是说关羽这门课的成绩在班级前10%。

3.前后函数

lead(n) / lag(n)

  • 用途:分组中位于当前行后n行(lead)/ 前n行(lag)的记录值。
  • 应用场景:求每个用户相邻两次浏览的时间差,可以参考我的这篇文章:
狗哥:数据分析|SQL面试题—相邻间隔问题​zhuanlan.zhihu.com
可以对窗口函数之后再加条件_数据分析|SQL窗口函数最全使用指南_第5张图片
SELECT 

可以对窗口函数之后再加条件_数据分析|SQL窗口函数最全使用指南_第6张图片

4.头尾函数——first_val(expr) / last_val(expr)。

  • 用途:得到分区中的第一个/最后一个指定参数的值。
SELECT 

可以对窗口函数之后再加条件_数据分析|SQL窗口函数最全使用指南_第7张图片

按姓名分组,截至到‘九阴真经’时,第一个记录为95分,最后一个记录为54分

5.其他函数

nth_value(expr, n)

  • 用途:返回窗口中第N个expr的值,expr可以是表达式,也可以是列名
SELECT 

可以对窗口函数之后再加条件_数据分析|SQL窗口函数最全使用指南_第8张图片

nfile()

  • 用途:将分区中的有序数据分为n个桶,记录桶号。
  • 此函数在数据分析中应用较多,比如由于数据量大,需要将数据平均分配到N个并行的进程分别计算,此时就可以用NFILE(N)对数据进行分组,由于记录数不一定被N整除,所以数据不一定完全平均,多出来的部分则依次加给第一组、第二组···直到分配完。

6.聚合函数

  • 用途:在窗口中每条记录动态应用聚合函数(sum/avg/max/min/count),可以动态计算在指定的窗口内的各种聚合函数值。
  • 应用场景:截至到当前课程,每个学生的总成绩/平均成绩/最高成绩/最低成绩/课程数是多少?

由于每个窗口函数的条件相同,所以这里将其起个别名w,每个窗口函数只要调用其别名w就好,如下:

SELECT 

可以对窗口函数之后再加条件_数据分析|SQL窗口函数最全使用指南_第9张图片

你可能感兴趣的:(可以对窗口函数之后再加条件)