解决数据排名问题——mysql中的窗口函数

对于SQL语句的使用,我们知道怎样使用它的增删改查,但是如果遇到这样的查询需求时,怎样得到各部门工资排名前N名员工列表,环比如何计算,查找各部门每人工资占部门工资的百分比。对于这写类型的查询需求,传统的查询语句解决起来非常的繁琐,但要解决此类问题,最方面的就是使用窗口函数。

             解决数据排名问题——mysql中的窗口函数_第1张图片

 

窗口函数的定义

        什么是窗口函数,窗口的概念十分重要,可以理解为记录集合,窗口函数也就是满足某种条件的记录集合上执行的特殊函数,对于每条记录都要在此窗口内执行函数,有的函数,随着记录不同,窗口大小都是固定的,这种属于静态窗口,有的函数则相反,不同的记录对应着不同的函数。窗口函数也叫OLAP函数,可以对数据库数据进行实时分析处理

        窗口函数和聚合函数有所不同,聚合函数时将多个记录聚合在一起,而窗口函数时每条记录都会执行,有几条记录执行完还是几条

按照功能划分,可以将窗口函数分为下面5种类型

  • 序号函数:row_number()/rank()/dense_rank()

  • 分布函数:percent_rank()/cume_dist()

  • 前后函数:lag()/lead()

  • 头尾函数:first_val()/last_val()

  • 其他函数:nth_value()/nfile()

1、窗口函数的使用

# 窗口函数语法<窗口函数> over (partition by <要分组的列名> order By <要排序的列名>)

1、窗口函数。这里主要介绍两种常见的窗口函数,(1)专用函数(row_number()、rank()、dense_rank())(2)聚合函数作为窗口函数使用(sum()、avg())

2、partition by 子句:窗口按照那些字段进行分组,窗口函数在不同的分组上分别执行,可以省略

3、原则上窗口函数只能写在select 子句中,不用在where和group by子句中使用、

4、order by 子句中可以通过desc、asc指定降序或者升序,如果省略,默认会按照升序asc进行排序

示例1:按照每个班级进行排名select *,rank() over(partition by 班级 over By 成绩 desc)as 排名from table1

结果展示:

学号 班级 成绩 排名
001 1 90 1
002 1 80 2
003 1 70 3
004 2 90 1
005 2 80 2
示例2:函数之间的对比展示select *,rank() over (order by 成绩 desc)as 排名1,          dense_rank() over(order by 成绩 desc)as 排名2,          row_number() over(order by 成绩 desc)as 排名3from table1;
学号 班级 成绩 排名1 排名2 排名3
001 1 98 1 1 1
002 3 97 2 2 2
003 2 96 3 3 3
004 1 95 4 4 4
005 1 95 4 4 5
006 3 90 6 5 6

解释:

rank()函数:计算排序时,如果有相同位次的记录,会占用下一名次的位置

dense_rank()函数:计算排序时,如果有相同位次的记录,不占用下一名次位置

row_number函数:计算排序时,不会出现相同位次的记录,是连续的位次

示例3:使用聚合函数作为窗口函数select *,sum(成绩) over (order by 学号)as 总和,          avg(成绩) over (order by 学号)as 平均值,          count(成绩) over (order by 学号)as 计数,          min(成绩) over (order by 学号)as 最小值from 班级表​​​​​​​

2、常见窗口函数案例

1、排名问题​​​​​​​

示例:排名函数之间的对比展示select *,rank() over (order by 成绩 desc)as 排名1,          dense_rank() over(order by 成绩 desc)as 排名2,          row_number() over(order by 成绩 desc)as 排名3from table1;
学号 班级 成绩 排名1 排名2 排名3
001 1 98 1 1 1
002 3 97 2 2 2
003 2 96 3 3 3
004 1 95 4 4 4
005 1 95 4 4 5
006 3 90 6 5 6

2、topN问题​​​​​​​

示例:找出每组最大的N条记录select * from (select * ,row_number() over (partition by 课程号1order by 成绩 desc)as 排名 from table)as a where 排名<=2;
学号 课程号 成绩 排名
001 1 98 1
002 1 97 2
003 2 87 1
004 2 80 2
005 3 60 1

3、每组之间进行比较​​​​​​​

示例:每组之间的比较(查找单科成绩高于该科目平均成绩的名单)select * from (select *,avg(成绩) over (partition by 科目)as 各科平均成绩 from table)as awhere a.成绩>a.各科平均成绩
学号 科目 成绩 各科平均成绩
001 科1 90 89
002 科2 98 90
003 科3 78 76
004 科4 89 67

随着大数据的时代的到来,数据变得越来越重要,数据可以帮助我们来看清行业的本质,也可以帮助我们更加快速的了解一个行业,关注公众号——有趣的数据,走进数据的时代。

解决数据排名问题——mysql中的窗口函数_第2张图片

 

你可能感兴趣的:(mysql数据库)