MySQL窗口函数须知

一. 窗口函数

1.应用场景

在实际工作中【组内排名】需要运用sql高级功能窗口函数。

排名问题:每个部门按业绩排名
TopN问题: 找出每个部门排名前N的员工。

2.窗口函数定义:

窗口函数(OLAP函数:online analytical processing)可以对数据库进行实时分析处理

3.函数语法

<窗口函数> over (partition by <用于分组的列名>
order by <用于拍排序的列名>)

3.函数语法

<窗口函数> over (partition by <用于分组的列名>
order by <用于拍排序的列名>)

1)<窗口函数>的位置,可以存放2种函数:

  • 专用窗口函数,包括rank, dense_rank, row_number等
  • 聚合函数:如sum, avg,count,max,min等

2) 窗口函数原则上只能写在select子句中,因为窗                                口函数对where or group by子句处理后的结果进行操作

二、窗口函数的使用

  1. rank函数 :案例1:
  • 目的:每个班级内按成绩排名
  • 数据理解:现在的数据一共有3个字段,学号,班级和成绩
  • 代码:select *, rank() over(partition by 班级 order by desc) as ranking from 班级表

按班级分组。partition by用来对表分组。这个例子中用班级分组。

按成绩排名:order by子句的功能是对分组后的结果进行排序,默认是升序(asc)

2. partition by和group by的区别

  • group by分组汇总后改变了表的行数,一行只有一个类别。
  • partition by和rank函数不会减少原表中的行数

 

3. 总结

partition by 分组后的结果称为窗口,表示范围的意思。窗口函数功能如下:

  • 同时具有分组和排序功能
  • 不减少原表的行数
  • 语法如下
<窗口函数> over (partition by <用于分组的列名>
order by <用于排序的列名>)

三、其他专用窗口函数

  1. rank, dense_rank 与 row_number的含义
select *, rank() over(order by desc) as ranking,
select *, dense_rank() over( order by desc) as dese_rank,
select *, row_number() over( order by desc) as row_number from 班级表

  • rank : 5,5,5,8。 有并列名次占用下一个名次的位置
  • dense_rank: 5556. 有并列名词不占用下一名次的位置
  • row_number:5678。不考虑并列名次的情况
  • 上述函数后面的括号不需要任何参数。保持()空着就可以

四、聚合函数作为窗口函数

  1. 聚合函数的语法

聚合函数的语法与专用窗口函数的语法完全相同,只需要把聚合函数写在窗口函数的位置即可,但是函数后括号不能为空,例如sum(成绩)。

select *, sum(成绩) over ( order by 学号)as current_sum,
avg(成绩) over ( order by 学号)as current_avg,

count(成绩) over ( order by 学号)as current_count,
max(成绩) over ( order by 学号)as current_max,
min(成绩) over ( order by 学号)as current_min,
from 班级表;

 

2. 聚合函数的理解

  • sum聚合函数是对自身记录,及位于自身记录以上的数据进行求和的结果。例如0005号,在使用sum窗口函数后的结果,是对0001-00005号全部求和。

 

  • 平均,计数,最大/最小值同上

3. 聚合函数的作用

  • 可以在每一行的数据里直观的看到,截至到本行数据,统计数据是多少(最大值,最小值等)
  • 可以看出每一行数据,对整体统计数据的影响

五、窗口函数的移动平均

  1. 代码理解
select *, avg(成绩) over (order by 学号  rows 2 preceding)as curent_avg from 班级表

  • rows+num+preceding:rows和preceding从翻译角度是之前的行,中间num表示数字
  • rows 2 preceding表示之前2行。即得到的结果是自身记录及前2行的平均。
  • 例如0005号同学,即0003、0004和0005 三位同学的平均值
  • 在移动平均中,被选出的数据构成了一个框架

2. 窗口函数作用

通过preceding关键字调整作用的范围,在以下场景非常使用

  • 在公司业绩排名中,可以通过移动平均,直观的查看与相邻名次业绩的平均,求和等统计数据
  • 在管理咨询当中可以通过这个窗口函数,进行集中度/市场占比的的计算

六、窗口函数总结

  1. 注意事项

partition子句可以省略,省略就是不指定分组。

2. 总结

1)窗口函数语法:

<窗口函数> over (partition by <用于分组的列名>
order by <用于拍排序的列名>)

2)<窗口函数>的位置,可以存放2种函数:

  • 专用窗口函数,包括rank, dense_rank, row_number等
  • 聚合函数:如sum, avg,count,max,min等

3) 功能:

  • 同时具备分组和排序功能
  • 不减少原表的行数,所以经常用来在每组内排名

4)窗口函数原则上只能写在select子句中

5)使用场景

  • 经典topN问题:找出每个部门排名前N的员工进行奖励
  • 经典排名问题:业务需求【在每组内排名】,比如,每个部门按业绩进行排名
  • 在每个组里比较的问题:比如查找每个组大于平均值的数据,a)使用窗口函数案例 b)使用关联子查询
  • 累计求和问题

案例1:面试经典排名问题

答案:

select *, dense_rank() over ( order by 成绩 desc)as dese_rank from 班级表

select score, dense_rank() over(order by score desc) as rank from scores

案例2:面试经典TOPN问题

答案:

select* 
from(
    select * ,row_number() over (partition by 姓名order by 成绩 desc) as ranking 
    from 成绩表)as a 
where ranking <=2;

模板:

# topN 问题模板

select *,
from(
    select *, row_number() over (partition by 要分组的列名 order by 要排序的列名 desc)as ranking 
    from 表名) as a 
where ranking<=N;

案例3:累计求和问题

答案:

select 雇员编号,薪水,sum(薪水) over(order by 雇员编号) as 累计薪水 
from 薪水表 
where 结束日期=’9999-01-01‘

案例4:如何在每个组里比较

答案:

select 
from(
    select * , avg(成绩)over (partition by 科目)as avgscore 
    from score )as b 
where 成绩>avg_score

七、存储过程

1.存储过程是什么

在工作里遇到重复性的工作,把常用的sql写好存储起来,就是存储过程。遇到相同的问题,直接使用存储过程就好了,不用再重新写一遍sql。提高工作效率。

2. 如何使用存储过程

使用存储过程需要: a)先定义存储过程;b)使用已经定义好存储过程

1)无参数的存储过程

A. 语法形式:

create procedure 存储过程名称() begin<sql语句>;
end;

语法里begin---end用于表示sql语句的开始和结束。语法里的【sql语句】就是重复使用的sql语句。

B. 案例

  • 创建存储过程

  • 使用存储过程

2)有参数的存储过程

A. 语法形式:

create procedure 存储过程名称(参数1,参数2,参数3---) begin<sql语句>;
end;

B. 案例(针对有条件的sql语句)

  • 创建存储过程

 其中getNum是存储过程名,其中num表示参数,而varchar(100)表示字符串类型;使用了where 学号=num就可以灵活的按照业务需求来查询。

  • 使用存储过程

3)默认参数存储过程

  • in 输入参数:参数初始值在存储过程前被指定为默认值,在存储过程中修改该参数的值不能被返回

out输出函数:参数初始值为空,该值可在存储过程内部被改变,并可返回

inout输入输出参数:参数初始值在存储过程前别指定为默认值,并且可在存储过程中被改变和在调用完毕后可被返回

3. 注意事项

  • 定义存储过程语法里的sql语句代码是完整的,必须用[;]结尾
  • 定义不同的存储过程,要使用不同的存储过程名,相同名字会报错
  • 存储过程和视图的差别:视图只有固定的sql语句,方便重复查询;存储过程等于编程,可以是实现复杂的操作。
  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

利威尔·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值