mysql之窗口函数练习

news/2024/5/3 11:38:36/文章来源:https://blog.csdn.net/weixin_48077303/article/details/129666318

🍊今天复习一下mysql中的窗口函数,主要是通过几道练习题复习和加深一下对窗口函数的理解,对往期内容感兴趣的同学可以参考如下内容👇:

  • 链接: 牛客SQL大厂真题——某音短视频.
  • 链接: 京东数据分析SQL面试题.
  • 链接: 百度用户增长SQL面试题.

🌰话不多说,让我们开始今日份的学习吧。

目录

  • 1. 窗口函数
    • 1.1 排序函数
    • 1.2 聚合函数
    • 1.3分析函数
  • 2. 窗口函数练习
    • 2.1 每类试卷得分前3名
    • 2.2 第二快/慢用时之差大于试卷时长一半的试卷
    • 2.3 连续两次作答试卷的最大时间窗
    • 2.4 近三个月未完成试卷数为0的用户完成情况
    • 2.5 未完成率较高的50%用户近三个月答卷情况
    • 2.6 试卷完成数同比2020年的增长率及排名变化
  • 3. 总结

1. 窗口函数

MySQL中的窗口函数(Window Functions)是一种用于计算和分析数据集中的子集的函数,这些函数在计算聚合值时可以对数据进行分组、排序、过滤等操作。它们与GROUP BY语句不同,GROUP BY语句只能进行一次分组,而窗口函数可以根据不同的条件进行多次分组。

窗口函数可以使用OVER子句指定分组、排序和窗口的范围。通常情况下,窗口函数可以分为三类:排名函数、聚合函数和分析函数。

1.1 排序函数

排序函数用于计算数据集中某个值在排序后的位置或排名。在MySQL中,常见的排序函数包括:

  • RANK():计算排名,并且当值相同时会出现“并列排名”。
  • DENSE_RANK():计算排名,如果有并列排名则会跳过排名,下一个排名不会重复。
  • ROW_NUMBER():计算每行的行号。

1.2 聚合函数

聚合函数用于对分组数据进行计算,例如计算分组中的平均值、总和、最大值和最小值等。常见的聚合函数包括:

  • SUM():计算分组中所有数值的总和。
  • AVG():计算分组中所有数值的平均值。
  • COUNT():计算分组中的记录数。
  • MAX():计算分组中所有数值的最大值。
  • MIN():计算分组中所有数值的最小值。

1.3分析函数

分析函数用于在保持数据集原有排序的情况下计算某个值。常见的分析函数包括:

  • LAG():返回指定行之前的某一行。
  • LEAD():返回指定行之后的某一行。
  • FIRST_VALUE():返回第一个值。
  • LAST_VALUE():返回最后一个值。
  • NTILE():将分组划分为相同大小的桶,返回桶的编号。

窗口函数提供了更灵活、更高效的数据分析功能,可以帮助我们更好地理解数据,找到数据中的趋势和规律。

2. 窗口函数练习

本次来做几道比较有意思的sql题,题目来源于牛客网,这几道题的通过率大多都在30%以下,于是自己亲自做了尝试,觉得很有参考价值。
链接: 进阶篇的窗口函数练习

在这里插入图片描述

2.1 每类试卷得分前3名

描述:有两张表,分别为试卷信息表examination_info,试卷作答记录表exam_record,如下:
在这里插入图片描述
在这里插入图片描述
需要找到每类试卷得分的前3名,如果两人最大分数相同,选择最小分数大者,如果还相同,选择uid大者。由示例数据结果输出如下:

在这里插入图片描述
题目的详细链接: 题目详情

解题思路:我们还是对最终的答案进行一步一步拆解,首先找到用户在某一门考试下的最小分数和当前排名,第二个子查询查找出某一个用户在某一门考试下的最高分,也就每一门考试只保留一个用户的最高分,最后再根据要求取前3名排序输出即可。

selecttmp2.tag,tmp2.uid,tmp2.rk
from(selecttmp1.exam_id,tmp1.tag,tmp1.uid,row_number() over (partition by tmp1.tag order by
tmp1.score desc,tmp1.min_score desc,tmp1.uid desc) rkfrom(selectt1.exam_id,t2.tag,t1.uid,t1.score,min(t1.score) over (partition by t1.uid,t2.tag) min_score,row_number() over (partition by t1.uid,t2.tag order by t1.score desc) max_scorefromexam_record t1left join examination_info t2 on t1.exam_id = t2.exam_id) tmp1wheretmp1.max_score = 1) tmp2
wheretmp2.rk <= 3

2.2 第二快/慢用时之差大于试卷时长一半的试卷

题目描述:现在有两张表:试卷信息表examination_info,试卷作答记录表exam_record
在这里插入图片描述
在这里插入图片描述
找到第二快和第二慢用时之差大于试卷时长的一半的试卷信息,按试卷ID降序排序。由示例数据结果输出如下:
在这里插入图片描述
题目链接: 详细连接
解题思路:我们主要是需要取出第二快和第二慢,于是我们在第一个字查询里面给做题快(时间升序)和慢(时间倒序)打上标记,在第二个子查询里面选出排名为2的数据,则可以选出第二快与第二慢,最后分组筛选出符合条件的数据即可。

selecttmp1.exam_id,tmp1.duration,tmp1.release_time
from(selectt1.exam_id,t1.start_time,t1.submit_time,t2.duration,t2.release_time,timestampdiff (second, start_time, submit_time) diff_time,row_number() over (partition byexam_idorder bytimestampdiff (minute, start_time, submit_time) desc) quick_rk,row_number() over (partition byexam_idorder bytimestampdiff (minute, start_time, submit_time)) slow_rkfromexam_record t1left join examination_info t2 on t1.exam_id = t2.exam_idwheret1.submit_time is not null) tmp1
wherequick_rk = 2or slow_rk = 2
group bytmp1.exam_id,tmp1.duration,tmp1.release_time
having(max(tmp1.diff_time) - min(diff_time)) / 60 > tmp1.duration / 2
order bytmp1.exam_id desc

2.3 连续两次作答试卷的最大时间窗

描述:现有试卷作答记录表exam_record
在这里插入图片描述
需要计算在2021年至少有两天作答过试卷的人中,计算该年连续两次作答试卷的最大时间窗days_window,那么根据该年的历史规律他在days_window天里平均会做多少套试卷,按最大时间窗和平均做答试卷套数倒序排序。由示例数据结果输出如下:
在这里插入图片描述
题目链接: 详细连接
解题思路:这块很多同学会想到自连接,其实不到迫不得,不要使用自连接,会影响查询销量,这里我们使用lead函数,可以取下一条数据,这样就可以实现自连接的效果。


select 
tmp1.uid,
max(tmp1.diff_day)+1 days_window,
round(count(1)*(max(tmp1.diff_day)+1)/(datediff(max(start_day),min(start_day))+1),2) avg_exam_cnt
from (
select 
uid,
date(start_time) start_day,
ifnull(lead(date(start_time))over(partition by uid order by start_time),date(start_time))next_day,
datediff(ifnull(lead(date(start_time))over(partition by uid),date(start_time)),date(start_time)) diff_day
from exam_record t1
where year(start_time)='2021'
)tmp1
group by tmp1.uid
having days_window>1
order by days_window desc,avg_exam_cnt desc

2.4 近三个月未完成试卷数为0的用户完成情况

描述:现有表试卷作答记录表exam_record
在这里插入图片描述
需要找到每个人近三个有试卷作答记录的月份中没有试卷是未完成状态的用户的试卷作答完成数,按试卷完成数和用户ID降序排名。由示例数据结果输出如下:
在这里插入图片描述
题目链接: 详细连接
解题思路:这道题需要判断进3个月和月份中是未完成状态,因此我们需要首先对未完成的试卷进行打标,然后根据月份进行排序,这样我们就得到了一个带有是否完成试卷标记以及排序的表,最后我们根据uid进行分组,选出完成标记与表中所有数据行相等的uid说明该用户都完成了试卷,再选择前三即可。


select
tmp1.uid,count(tmp1.start_time) exam_complete_cntfrom(
select *,
case when submit_time is null then 0 else 1 end sub_tag ,
dense_rank()over(partition by uid order by date_format(start_time,'%Y-%m') desc) mon_rk
from exam_record
)tmp1
where  tmp1.mon_rk<4 
group by tmp1.uid
having sum(sub_tag)=count(1)
order by exam_complete_cnt desc ,tmp1.uid desc

2.5 未完成率较高的50%用户近三个月答卷情况

这道题是我觉得最难的,我用了一些自连接的方式来解决该问题。
该题的描述:有户信息表user_info、试卷信息表examination_info、试卷作答记录表exam_record
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
需要计算SQL试卷上未完成率较高的50%用户中,6级和7级用户在有试卷作答记录的近三个月中,每个月的答卷数目和完成数目。按用户ID、月份升序排序。

在这里插入图片描述
题目链接: 详细连接
解题思路:这道题需要解决前50%如何计算?主要有几种思路:1.count出所有的数据,计算行数,然后计算中间值。2. 窗口函数计算行数求中间值。而思路是首先计算出每个用户的完成率,后续再对完成率进行排序,塞选出满足条件的用户,因此第一个临时表计算的就是每个用户的完成率,然后在主体中进行排序,根据max(排序的序号)函数计算50%的值mid,然后用排序的序号与mid进行比较,大于等于mid的就是前50%。

with user_tab as(
select
uid,tag,level,
row_number()over(order by ok_rate desc) rk
from(
select
uid,tag,level,
count(case when tmp1.tag='sql' and tmp1.sub_tag=1 then 1 else null end)/count(case when tmp1.tag='sql' then 1 else null end) ok_rate
from
(
select
t1.uid,
t1.exam_id,
start_time,
t2.tag,
t3.level,
case when submit_time is null then 0 else 1 end sub_tag,
case when t2.tag ='SQL'  then 1 else 0 end sql_tag
from exam_record t1
left join examination_info t2
on t1.exam_id=t2.exam_id
left join user_info t3
on t1.uid=t3.uid
)tmp1
group by uid,tag,level
having tag='sql'
)tmp2
)select
uid,start_mon,count(*),count(sub_tag2)
from(
select uid,date_format(start_time,'%Y%m') start_mon,
case when submit_time is null then null else submit_time end sub_tag2,
dense_rank()over(partition by uid order by date_format(start_time,'%Y%m') desc ) rk2
from exam_record
where uid in (
select uid
from 
(
select  uid,tag,level,rk,max(rk)over(partition by null)/2 bi_rk
from  user_tab)tab1
where rk>bi_rk and level in (6,7)))tab2
where rk2<=3
group by uid,start_mon
order by uid,start_mon

2.6 试卷完成数同比2020年的增长率及排名变化

描述:有试卷信息表examination_info、作答记录表exam_record
在这里插入图片描述
在这里插入图片描述
题目链接: 详细连接
需要计算2021年上半年各类试卷的做完次数相比2020年上半年同期的增长率(百分比格式,保留1位小数),以及做完次数排名变化,按增长率和21年排名降序输出。
在这里插入图片描述
解题思路:这里我们需要先筛选出2020年和2021年上半年的答题记录,然后计算该时间段内答题的数据,接着利用leader函数选出同一tag下不同年份的数据,最后计算相关值即可。(这里需要注意两个rk相减出现负数会报错,需要转换类型。)

select
tmp3.tag,
tmp3.next_num exam_cnt_20,
tmp3.sub_tag exam_cnt_21,
concat(round((tmp3.sub_tag-tmp3.next_num)/tmp3.next_num*100,1),'%') growth_rate,
tmp3.next_rk exam_cnt_rank_20,
tmp3.rk1 exam_cnt_rank_21,
cast(tmp3.rk1 as signed)-cast(tmp3.next_rk as signed)
from(
select
*,
lead(sub_tag)over(partition by tmp2.tag order by start_year desc) next_num,
lead(rk1)over(partition by tmp2.tag order by start_year desc) next_rk
from(selecttmp1.tag,start_year,sub_tag,rank() over (partition by start_year order by
sub_tag desc) rk1from(selectt2.tag,year (t1.start_time) start_year,count(case when submit_time is null then null else t1.uid end) sub_tagfromexam_record t1left join examination_info t2 on t1.exam_id = t2.exam_idwheret1.submit_time is not nulland month (start_time) < 6 and year(start_time)in (2020,2021)group byt2.tag,year (t1.start_time)) tmp1) tmp2
)tmp3
where tmp3.next_num is not null and tmp3.next_rk is not null
order by growth_rate desc,exam_cnt_rank_21 desc

3. 总结

这些题目都是自己写的,都很经典,大家有其他的解题思路可以一起分享。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_274001.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java实习生------MySQL10道面试题打卡

今日语录&#xff1a;“没有执行力&#xff0c;就没有竞争力 ”&#x1f339; 参考资料&#xff1a;图解MySQL、MySQL面试题 1、事务有哪些特性&#xff1f; 原子性&#xff1a; 一个事务中的所有操作&#xff0c;要么全部完成&#xff0c;要么全部不完成&#xff0c;不会出现…

Linux系统的安装以及参数配置 -- VMware(虚拟机)安装--ubuntu 20.04--VMware Tools工具安装

Linux系统的安装以及参数配置 PS&#xff1a;本文章为上课后整理笔记&#xff0c;作为以后学习工作的学习使用&#xff0c;也作为一次课程记录 一、Linux系统的安装常用方法 – 3种 1.直接Linux操作替换Windows – 专业Linux开发者 – 接受Linux相关软件的使用 2.安装双系统…

诗佛王维,眼前的苟且和远方的田野?

转自&#xff1a;媲美李白杜甫的诗人&#xff0c;他的人生可以复制_百科TA说 (baidu.com)他受到的羁绊&#xff0c;他做出的选择&#xff0c;提供了一种温润平和的过日子模式。大部分人无法决绝地脱离社会&#xff0c;隐遁起来&#xff0c;也无法在社会中不计底线&#xff0c;混…

JavaScript性能优化小窍门汇总(含实例)

在众多语言中&#xff0c;JavaScript已经占有重要的一席之地&#xff0c;利用JavaScript我们可以做很多事情 &#xff0c; 应用广泛。在web应用项目中&#xff0c;需要大量JavaScript的代码&#xff0c;将来也会越来越多。但是由于JavaScript是一个作为解释执行的语言&#xff…

Vue|样式绑定

class 与 style 是 HTML 元素的属性&#xff0c;用于设置元素的样式&#xff0c;我们可以用 v-bind 来设置样式属性。Vue.js v-bind 在处理 class 和 style 时&#xff0c; 专门增强了它。表达式的结果类型除了字符串之外&#xff0c;还可以是对象或数组。 文末名片获取源码 精…

根据平均分来划分等级-课后程序(JavaScript前端开发案例教程-黑马程序员编著-第2章-课后作业)

【案例2-1】 根据平均分来划分等级 一、案例描述 考核知识点 switch语句 练习目标 掌握switch语句的使用。 需求分析 switch语句也是多分支语句&#xff0c;针对某个表达式的值做出判断&#xff0c;来决定执行哪一段代码&#xff0c;本案例用于实现根据输入的小明同学的5门课…

百度CTO王海峰:全栈AI技术加持,打造新一代大语言模型文心一言

3月16日&#xff0c;百度在北京总部召开新闻发布会&#xff0c;百度创始人、董事长兼首席执行官李彦宏和百度首席技术官王海峰出席&#xff0c;李彦宏展示了新一代知识增强大语言模型文心一言在文学创作、商业文案创作、数理逻辑推算、中文理解、多模态生成五个使用场景中的综合…

【linux】管道pipe(),dup()系统调用

int pipe(int p[2]) 函数作用&#xff1a;生成一个管道&#xff0c;将管道读端的文件标识符存到p[0]中&#xff0c;将管道写端的文件标识符存到p[1]中。返回值&#xff1a;若成功返回0&#xff0c;失败返回-1 管道的理解 如图&#xff0c;当创建完管道以后的父进程fork出两个子…

Python中模块是个啥

昨天有粉丝问我说&#xff0c;啥是模块&#xff1f;经常听别人口中提这个词&#xff0c;但就是不懂。 模块可以认为是一盒主题积木&#xff0c;通过它可以拼出某一主题的东西。这与之前介绍的函数不同&#xff0c;一个函数相当于一块积木&#xff0c;而一个模块中可以包括很多函…

【C++进阶】unordered_set和unordered_map的介绍及使用

文章目录unordered系列容器介绍unordered_setunordered_set的模板参数unordered_set的函数接口介绍unordered_set的重要接口的使用构造函数增删查迭代器的使用unordered_mapunordered_map的模板参数unordered_map的函数接口介绍unordered_map的重要接口的使用增删查改迭代器的使…

EMQ 南洋万邦云边一体化方案:激活数据潜力,打造智慧工业园区

在工业 4.0 的浪潮之中,全球制造业再度振兴和崛起,并经历着前所未有从流程驱动转向数据驱动的变革。 近年来,数智化绿色工厂正在成为制造业竞争力的主要驱动力,依托物联网、工业互联网,人工智能等先进制造技术的深度融合,智能工厂变得更高效、更灵活,拥有更高的交付韧性和成本…

解忧杂货铺(四):Hightec生成HEX方法+小功能开启

目录 1、概述 2、 4.6.6的生成方法 3 、HighTEC4.9.3的生成.hex方法 4、MAP文件生成方法 5、elf生成 6、编译优化 7、输出编译过程中的详细信息 8、快速定位内存 1、概述 本文章纯属整合&#xff0c;大部分属于外链&#xff0c;补充一下&#xff0c;后面是自己记录的了…

由浅入深之字符串的算法题(vs: chatGPT做算法)

背景俗话说&#xff0c;温故而知新。chatGPT效果太惊艳了&#xff01;简直就是碾压的效果。但是还要有希望&#xff0c;先拾取&#xff0c;再创新。先了解&#xff0c;再超越吧。ps: 再刷最后一遍算法题思路。顺便基于chatGPT3.5感受一下大模型的魔力。字符串基础C/C每个字符串…

编程题]组队竞赛(Java实现)

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点!人生格言&#xff1a;当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔&#x1f9be;&am…

十七、队列

文章目录1、基本概念&#xff08;队列实际上就是一个结构体&#xff0c;可以理解为就是一个数组&#xff09;2、使用场景&#xff1a;任务间或任务与中断间传递数据3、使用队列的好处&#xff08;1&#xff09;休眠唤醒&#xff08;2&#xff09;提高CPU利用率4、队列的核心5、…

WebService简单入门

1. JAX-WS发布WebService 创建web工程 创建simple包&#xff0c;和server、client两个子包。正常情况下server和client应该是两个项目&#xff0c;这里我们只是演示效果&#xff0c;所以简化写到一个项目中&#xff1a; 1.1 创建服务类Server package simple.server;import ja…

JavaScript正则表达式知识拓展总结

JavaScript的正则表达式是前端中比较重要的部分&#xff0c;正则表达式主要用于字符串处理&#xff0c;表单验证等场合&#xff0c;实用高效。JavaScript中的正则表达式比起C#中的正则表达式要弱很多&#xff0c;但基本够用了。在js中定义正则表达式很简单&#xff0c;有两种方…

搭建SFTP服务安全共享文件,实现在外远程访问「内网穿透」

文章目录1.前言2.本地SFTP服务器搭建2.1.SFTP软件的下载和安装2.2.配置SFTP站点2.3.Cpolar下载和安装3.SFTP服务器的发布3.1.Cpolar云端设置3.2.Cpolar本地设置4.公网访问测试5.结语1.前言 现在的网络发达&#xff0c;个人电脑容量快速上升&#xff0c;想要保存的数据资料也越…

DRBG_InstantiateSeeded调试-1

public 参数解析: standardEKPolicy: 837197674484b3f81a90cc8d46a5d724fd52d76e06520b64f2a1da1b331469aa(32bytes) rawCmdBuf 命令数据: 800200000063000001314000000100000009400000090000010000000400000000003a0001000b000300720020837197674484b3f81a90cc8d46a5d724fd5…

Baumer工业相机堡盟相机如何使用PixelTransformation像素转换功能(像素转换功能的使用和优点以及行业应用)(C++)

项目场景 Baumer工业相机堡盟相机是一种高性能、高质量的工业相机&#xff0c;可用于各种应用场景&#xff0c;如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能&#xff0c;可以实时传输高分辨率图像。此外&#xff0c;该相机还具…