MySQL实战窗口函数SQL分析班级学生考试成绩及生活消费
作者:数据分析与统计学之美 发布时间:2024-01-15 08:56:14
一、背景介绍
今天,野鸡大学高(三)班的月考成绩出来了,这里先给大家公布一下各位同学的考试成绩。
接着,在给大家公布一下各位同学的生活消费情况。
下面我们利用上述考试成绩和生活消费记录,利用mysql做一个简单的分析。
当然,从本文标题就可以看出来。本文就是要结合这份数据,为大家讲述SQL “窗口函数” 应该怎么用?
包括你以后学习hive或者oracle数据库,或者说数据分析面试,这都将是一个很重要的知识点。
二、建表语句和插入数据
创建表格
create table exam_score(
sname varchar(20),
age int,
subject varchar(20),
score varchar(20)
)charset=utf8;
# ----------------------- #
create table cost_fee(
sname varchar(20),
buydate varchar(20),
buycost int
)charset=utf8;
插入数据
insert into exam_score values
('张三' , 18, '语文' , 90),
('张三' , 18, '数学' , 80),
('张三' , 18, '英语' , 70),
('李四' , 21, '语文' , 88),
('李四' , 21, '数学' , 78),
('李四' , 21, '英语' , 71),
('王五' , 18, '语文' , 95),
('王五' , 18, '数学' , 83),
('王五' , 18, '英语' , 71),
('赵六' , 19, '语文' , 98),
('赵六' , 19, '数学' , 90),
('赵六' , 19, '英语' , 80);
# ----------------------- #
insert into cost_fee values
('张三','2019-01-01',10),
('张三','2019-03-03',23),
('张三','2019-02-05',46),
('李四','2019-02-02',15),
('李四','2019-01-07',50),
('李四','2019-03-04',29),
('王五','2019-03-08',62),
('王五','2019-02-09',68),
('王五','2019-01-11',75),
('赵六','2019-02-08',55),
('赵六','2019-03-10',12),
('赵六','2019-01-12',80);
三、窗口函数分类介绍
在正式讲述 “窗口函数” 应用之前,我这里先带着大家梳理一遍 “窗口函数” 的基础。我们可以将窗口函数分为如下几类:
聚合函数 + over()搭配;
排序函数 + over()搭配;
ntile()函数 + over()搭配;
偏移函数 + over()搭配;
具体每一类,有哪些函数呢?观察下面的思维导图。
对于over()里面,这里还有两个常用的关键字,必须要讲述。如下:
partition by + 字段:你可以想象成group by关键字,就是用于 “分组” 的关键字;
order by + 字段:这个更容易理解,就是用于 “排序” 的关键字;
四、窗口函数应用
上面给大家介绍了若干常用的 “窗口函数”,这里利用文首创建的数据,讲讲 “窗口函数” 的应用。
希望大家通过每个案例,来总结一下每个函数的含义,这里就不详细写了。
1. 聚合函数 + over()搭配
① 计算每位同学的得分与平均值的情况
select
sname
,subject
,score
,avg(score) over(partition by sname) as avg_score
from
exam_score
结果如下:
② 计算每位同学1-3月消费情况和消费总额
select
sname
,buydate
,buycost
,sum(buycost) over(partition by sname) as sum_cost
from
cost_fee
结果如下:
③ 计算每位同学1-3月消费情况和累计消费总额
select
sname
,buydate
,buycost
,sum(buycost) over(partition by sname order by buydate) as sum_cost
from
cost_fee
结果如下:
注意: 结合②③,大家可以发现partition by结合order by,与不结合order by,得到的完全是不同的结果。一个是分组求总和(不加order by);一个是分组求累计和(加order by)。
2. 排序函数 + over()搭配
① 计算每个科目的排名,相同的分数排名不同,顺序依次增加
select
sname
,subject
,score
,row_number() over(partition by subject order by score) rank1
from
exam_score
结果如下:
② 计算每个科目的排名,相同的分数排名相同,余下排名跳跃增加
select
sname
,subject
,score
,rank() over(partition by subject order by score) rank1
from
exam_score
结果如下:
③ 计算每个科目的排名,相同的分数排名相同,余下排名顺序增加
select
sname
,subject
,score
,dense_rank() over(partition by subject order by score) rank1
from
exam_score
结果如下:
3. ntile()函数 + over()搭配
ntile()函数有点乱入的感觉,你不知道给它分哪一类。该函数主要用 “数据切分”。如果说这个函数还有点用的话,就是他也可以对数据进行排序,类似于上面提到的row_number()函数。
① 对exam_score表,进行整张表切分
select
sname
,subject
,score
,ntile(4) over() rank1
from
exam_score
结果如下:
不信你下去试一下,ntile()里面不管写哪个数字,好像都可以。
② 对exam_score表,按照subject分组切分
select
sname
,subject
,score
,ntile(4) over(partition by subject) rank1
from
exam_score
结果如下:
即使是分组切分,你也会发现,这样毫无意义,因为score并没有排序。
③ 对exam_score表,对score排序后,按照subject分组切分(最有用)
select
sname
,subject
,score
,ntile(4) over(partition by subject order by score) rank1
from
exam_score
结果如下:
注意: 仔细观察这种用法,基本可以等效row_number()函数,效果是一样的。
4. 偏移函数 + over()搭配
① 展示各位同学的“上次购买时间”和“下次购买时间”
注:对于第一天,显示 “first buy”;对于最后一天,显示 “last buy”;
select
sname
,buydate
,lag(buydate,1,'first day') over(partition by sname order by buydate) as 上次购买时间
,lead(buydate,1,'last day') over(partition by sname order by buydate) as 下次购买时间
from
cost_fee
结果如下:
② 截止到当前日期,每位同学的“首次购买时间”和“最后一次购买时间”
select
sname
,buydate
,first_value(buydate) over(partition by sname order by buydate) as 首次购买时间
,last_value(buydate) over(partition by sname order by buydate) as 最后一次购买时间
from
cost_fee
结果如下:
③ 展示每位同学的“首次购买时间”和“最后一次购买时间”
注意: 这里并没有说 “截止到当前日期”,请注意②③之间的区别呀。需求不同,结果就不同。
select
sname
,buydate
,first_value(buydate) over(partition by sname order by buydate) as 首次购买时间
,last_value(buydate) over(partition by sname ) as 最后一次购买时间
from
cost_fee
结果如下:
来源:https://huang-tong-xue.blog.csdn.net/article/details/115908762


猜你喜欢
- 本文实例讲述了python实现的简单FTP上传下载文件的方法。分享给大家供大家参考。具体如下:python本身自带一个FTP模块,可以实现上
- 废话不多说了,直接给大家贴代码了,具体代码如下所示:<html> <head> <script> fun
- 内置函数常用函数1.数学相关•abs(x)abs()返回一个数字的绝对值。如果给出复数,返回值就是该复数的模。>>>pri
- count()方法返回obj出现在列表的次数。语法以下是count()方法的语法:list.count(obj)参数
- 如下所示:# 返回一个列表中出现次数最多的元素def showmax(lt): index1 = 0&n
- 在日常的编程中,我经常需要标识存在于文本文档中的部件和结构,这些文档包括:日志文件、配置文件、定界的数据以及格式更自由的(但还是
- 相对或者绝对import 更多的复杂部分已经从python2.5以来实现:导入一个模块可以指定使用绝对或者包相对的导入。这个计划将移动到使绝
- Web性能优化最佳实践中最重要的一条是减少HTTP请求,它也是YSlow中比重最大的一条规则。减少HTTP请求的方案主要有合并JavaScr
- phpMyAdmin 是一套可以通过WEB来管理 MySQL-server 以及单一数据库的 PHP
- 备注:Oracle 19C一. Json数据存储看了下官网,Json数据一般使用varchar2(400),varchar2(32676)或
- 一 概念固定窗口就像是滑动窗口的一个特例,固定窗口是大小固定且不能随着时间而变化的。滑动时间窗口就是把一段时间片分为多个样本窗口,可以通过更
- 触发器权限和所有权CREATE TRIGGER 权限默认授予定义触发器的表所有者、sysadmin 固定服务器角色成员以及 db_owner
- DSDS应用场景1、背景“双卡手机”在中国手机市场占据近90%市场份额,随着软卡、云卡、eSIM的发展,双卡的应用也将更加广泛。此外,5G面
- 介绍今天有个不正经的需求,就是要快速做一个restful api的性能测试,要求测试在海量作业数据的情况下客户端分页获取所有作业的性能。因为
- 创建watermark.js文件let watermark = {}let setWatermark = (str) => { let
- 通用用法但上图的字段名,类型需要根据不同接口填写,如某服务接口:因而对应的上传代码如下:# 输出参数:请求响应报文import reques
- 本文实例为大家分享了Tensorflow实现神经网络拟合线性回归的具体代码,供大家参考,具体内容如下一、利用简单的一层神经网络拟合一个函数
- 最近工作中写了几个存储过程,需要向存储过程中传递字符串,因为SQL Server 2000中没有内置类似于 split 的函数,只好自己处理
- 最长公共子序列python实现,最长公共子序列是动态规划基本题目,下面按照动态规划基本步骤解出来。1.找出最优解的性质,并刻划其结构特征序列
- 我们知道在国内使用 Docker,无论是 Pull、Build 还是 Push 镜像都十分慢,因为毕竟很多源都是国外的源,下载和上传慢是必然