开始学习前,也是作为一个提醒,避免走弯路。先确认下自己的mysql版本是什么,mysql8.0以后才开始支持窗口函数。
1、什么是窗口函数?
窗口函数,也叫OLAP函数(Online Anallytical Processing,联机分析处理),可以对数据库数据进行实时分析处理。“窗口”,是范围的意思。
2、如何使用窗口函数?
窗口函数的基本语法如下:
例如下图,是班级表中的内容
解答:
查询结果:
接下来,就结合实例,给大家介绍几种窗口函数和窗口函数的用法。
1) 专用窗口函数,包括rank, dense_rank, row_number等专用窗口函数。
- rank函数:相同值排名相同,下一排名根据之前的记录个数而定
- dense_rank函数:相同值排名相同,排名连续不间断
- row_number函数:不管值是否相同,依次连续排名
对上面专用窗口函数的使用描述似乎不太好理解,有点懵。没关系,我们通过一个例子来厘清其中的区别。
题目:查询所有学生按成绩排名情况
解答:
得到结果:
rank函数:这个例子中是5位,5位,5位,8位,也就是如果有并列名次的行,会占用下一名次的位置。比如正常排名是1,2,3,4,但是现在前3名是并列的名次,结果是: 1,1,1,4。
dense_rank函数:这个例子中是5位,5位,5位,6位,也就是如果有并列名次的行,不占用下一名次的位置。比如正常排名是1,2,3,4,但是现在前3名是并列的名次,结果是: 1,1,1,2。
row_number函数:这个例子中是5位,6位,7位,8位,也就是不考虑并列名次的情况。比如前3名是并列的名次,排名是正常的 1,2,3,4。
最后,需要强调的一点是:在上述的这三个专用窗口函数中,函数后面的括号不需要任何参数,保持()空着就可以。
趁热打铁,我们再来看几道经典的面试题。
题目1:在上面的班级表(class)中,查询每个班级中学生成绩最大值所在行的数据
方法一:关联子查询
得到结果:
① 第一步,用rank窗口函数。先求得按班级分组并把成绩倒序排序的结果
得到结果:
最终查询结果:
题目2:查询各个班级成绩前两名的记录
解答:
得到结果:
聚和窗口函数和上面提到的专用窗口函数用法完全相同,只需要把聚合函数写在窗口函数的位置即可,但是函数后面括号里面不能为空,需要指定聚合的列名。
下面通过具体的题目来体会一下。
题目:按成绩升序排序后查询以下结果:当前累计成绩总分、成绩平均分、最高分成绩、最低分成绩、统计人数以及当前记录之前两位同学的平均成绩
解答:
查询结果是:
(1) <窗口函数>里面可以放以下两种函数:① 专用窗口函数
rank:相同值排名相同,下一排名根据之前的记录个数而定
dense_rank:相同值排名相同,排名连续不间断
row_number:不管值是否相同,依次连续排名② 聚合函数
sum:求和
avg:求平均值
max:求最大值
min:求最小值
count:计数
(2) 窗口函数的“窗口”可以进行“移动”,变成“窗口平移函数”
2. 窗口函数具备的功能
1)同时具有分组(partition by)和排序(order by)的功能
2)不减少原表的行数,所以经常用来在每组内排名(区别于group by)
group by分组汇总后改变了表的行数,一行只有一个类别。而partiition by和rank函数不会减少原表中的行数。例如下面统计每个班级的人数。
4. 使用窗口函数的注意事项
1)窗口函数原则上只能写在select子句中
2)partition子句可是省略,省略就是不指定分组。
3)注意各窗口函数的区别和使用条件
最后还要强调的是,尤其当语句复杂时,要牢记之前一直说的SQL语句书写顺序和运行顺序。在运行顺序中,select子句是最后被运行的。