SQL进阶day11——窗口函数

目录

1专用窗口函数

1.1 每类试卷得分前3名

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

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

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

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

2聚合窗口函数

2.1 对试卷得分做min-max归一化

2.2每份试卷每月作答数和截止当月的作答总数。

2.3 每月及截止当月的答题情况

1专用窗口函数

1.1 每类试卷得分前3名

我的代码:筛选好难,不懂啥意思

select tag tid,uid,rank()over(partition by tag order by score desc ) ranking
from examination_info ei join exam_record er
on ei.exam_id = er.exam_id
limit 3

正确代码:

select *
from (select tag tid,
uid,
rank()over(partition by tag order by max(score) desc,min(score) desc,max(uid) desc) ranking
from examination_info ei join exam_record er
on ei.exam_id = er.exam_id
group by tag,uid)t
where ranking<=3

复盘:

(1)排序:如果两人最大分数相同,选择最小分数大者,如果还相同,选择uid大者

ORDER BY MAX(score) desc ,MIN(score) desc,uid desc

(2)窗口函数

【排序窗口函数】

●   rank()over()——1,1,3,4

●   dense_rank()over()——1,1,2,3

●   row_number()over()——1,2,3,4

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

我的代码:没搞出来,好久没有弄窗口了,这个题好难

方法1:max(if)

select a.exam_id,b.duration,b.release_time  
from
(select exam_id,
row_number() over(partition by exam_id order by timestampdiff(second,start_time,submit_time) desc) rn1,
row_number() over(partition by exam_id order by timestampdiff(second,start_time,submit_time) asc ) rn2,
timestampdiff(second,start_time,submit_time) timex
from exam_record 
where score is not null) ainner join examination_info b on a.exam_id=b.exam_id
group by a.exam_id
#if(rn1=2,a.timex,0)后最大值肯定是第二位的a.timex了
having (max(if(rn1=2,a.timex,0))-max(if(rn2=2,a.timex,0)))/60>b.duration/2 
order by a.exam_id desc

方法2:分析(窗口)函数:NTH_VALUE

select distinct c.exam_id,duration,release_time from 
(select a.exam_id, 
nth_value(TIMESTAMPDIFF(minute,start_time,submit_time),2) over (partition by exam_id order by TIMESTAMPDIFF(minute,start_time,submit_time) desc ) as low_2,
nth_value(TIMESTAMPDIFF(minute,start_time,submit_time),2) over (partition by exam_id order by TIMESTAMPDIFF(minute,start_time,submit_time) asc) as fast_2,
duration,release_time
from exam_record a left join examination_info b on a.exam_id = b.exam_id) c 
where low_2-fast_2>duration*0.5
order by exam_id desc;

复盘:

(1)时间差函数:timestampdiff,如计算差多少分钟,timestampdiff(minute,时间1,时间2),是时间2-时间1,单位是minute

(2)如何取次最大和次最小呢:分析(窗口)函数:NTH_VALUE

NTH_VALUE (measure_expr, n) [ FROM { FIRST | LAST } ][ { RESPECT | IGNORE } NULLS ] OVER (analytic_clause)

(3)关于窗口函数,才发现我本地的数据库连接版本是5,只有MySQL8以上才能用窗口函数好像,所以不能在本地演练推导了。(我一点也不想升级,安装都很麻烦,升级的话肯定各种报错)

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

我的思路:(写不出来)

(1)先把每个用户作答时间用dateformat求出来

(2)在作差,应该可以用偏移分析函数:

【偏移分析函数】

●   lag(字段名,偏移量[,默认值])over()——当前行向取值“偏移量”行

●   lead(字段名,偏移量[,默认值])over()——当前行向取值“偏移量”行

例:

●      ,confirmed 当天截至时间累计确诊人数

●      ,lag(confirmed,1)over(partition by name order by whn) 昨天截至时间累计确诊人数

●      ,(confirmed - lag(confirmed,1)over(partition by name order by whn)) 每天新增确诊人数

 (3)然后选取最大的这个差值

正确代码:

select uid,max(datediff(next_time,start_time))+1 as days_window,round(count(start_time)/(datediff(max(start_time),min(start_time))+1)*(max(datediff(next_time,start_time))+1),2)as avg_exam_cnt
from(select uid,start_time,lead(start_time,1) over(partition by uid order by start_time) as next_timefrom exam_recordwhere year(start_time) = '2021')a
group by uid
having count(distinct date(start_time)) > 1
order by days_window desc,avg_exam_cnt desc

复盘:

(1)先找出uid, 开始时间,下次开始时间。条件是2021创建子表

下次开始时间用偏移分析函数:

●   lead(字段名,偏移量[,默认值])over()——当前行向取值“偏移量”行

select uid,start_time,lead(start_time,1) over(partition by uid order by start_time) as next_time
from exam_record
where year(start_time) = '2021'

(2)最大时间窗口 = max(datediff(next_time,start_time))+1

(3)平均做答试卷套数=作答的试卷数 / 作答期间 *最大时间窗口

= 3/7*6

= count(start_time)/

(datediff(max(start_time),min(start_time))+1)

*(max(datediff(next_time,start_time))+1)

= round(count(start_time)/

(datediff(max(start_time),min(start_time))+1)

*(max(datediff(next_time,start_time))+1),2) #保留两位小数

(4)时间作差要用时间差函数datediff,不能直接相减:结果会是不一样的

(5)datediff()函数 与 timestampdiff()函数的区别

//语法
DATEDIFF(datepart,startdate,enddate)

SELECT DATEDIFF('2018-05-09 08:00:00','2018-05-09') AS DiffDate;//结果 0 ; 表示 2018-05-09 与 2018-05-09之间没有日期差。这里是不比较时分秒的。下面验证带上时分秒有没有差别。SELECT DATEDIFF('2018-05-09 00:00:00','2018-05-09 23:59:59') AS DiffDate;//结果 0 ;SELECT DATEDIFF('2018-05-08 23:59:59','2018-05-09 00:00:00') AS DiffDate;//结果 -1;SELECT DATEDIFF('2018-05-09 00:00:00','2018-05-08 23:59:59') AS DiffDate;
//结果 1;

 

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

我的代码:思路是这样,报错是必然的

# 先按照uid划分,找出都完成了的,
select uid,
rank()over(partition by uid order by start_time) exam_complete
from exam_record
group by uid
having count(start_time) = count(submit_time) #不对,这样不是每个uid的count# 再按照时间划分,找出3个以上的
select uid,
count(exam_complete) exam_complete_cnt
from 
(select uid,
rank()over(partition by uid order by start_time) exam_complete
from exam_record
group by uid
having count(start_time) = count(submit_time))a
where exam_complete_cnt>3

大佬代码:发现这个答案和我的好像,我再改改

select uid,count(start_time) as exam_complete_cnt
from(select *,dense_rank() over(partition by uid order by date_format(start_time,'%Y%m') desc) as rankingfrom exam_record) a
where ranking <= 3    -- 这里也不能用where ranking <= 3 and submit_time is not null,而要将用户分组后,用having判断
group by uid
having count(score) =  count(uid)
order by exam_complete_cnt desc, uid desc

我的代码改正:

select uid,
count(start_time) as exam_complete_cnt
from
(select *, #后面要用到start_time和submit_time,select也要用到uid,用*全部返回吧
dense_rank()over(partition by uid order by date_format(start_time,"%Y%m") desc) ranking
from exam_record)a
where ranking <=3 #把前面3个月的都要进行计数
group by uid
having count(start_time) = count(submit_time)
order by exam_complete_cnt desc, uid desc

复盘:

(1)这里不能用rank,加引号也不行,难道是和函数名重复了?改为ranking就好了

(2)窗口函数,等着二刷吧,有点小难

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

我的代码:思路是这样,报错是必然的

# 先筛选出SQL试卷上,未完成率较高的50%用户,6级和7级用户
select *,count(er.submit_time)/count(er.start_time) complete_rate,
rank()over(partition by u.uid order by complete_rate) ranking
from examination_info ei join exam_record er
on ei.exam_id = er.exam_id
join user_info u on u.uid = er.uid
group by u.uid
having ei.tag = 'SQL' and u.level in (6,7) and ranking<0.5
# 子表用户在有试卷作答记录的近三个月中,每个月的答卷数目和完成数目
# 完整代码:
select
uid,
start_month,
count(start_time) total_cnt,
count(submit_time) complete_cnt
from(select *,count(er.submit_time)/count(er.start_time) complete_rate,
rank()over(partition by u.uid order by complete_rate) ranking,
dense_rank()over(partition by uid order by date_format(submit_time,"%Y%m") desc) rankingmonth
from examination_info ei join exam_record er
on ei.exam_id = er.exam_id
join user_info u on u.uid = er.uid
group by u.uid
having ei.tag = 'SQL' and u.level in (6,7) and ranking<0.5)a
where rankingmonth <=3
group by date_format(submit_time,"%Y%m")

大佬代码:好牛,我啥时候能这个水平

# 第一步,先找出未完成率前50%高的用户ID,注意这里需要的sql试卷
with rote_tab as 
(select t.uid,t.f_rote,row_number()over(order by t.f_rote desc,uid) as rank2
,count(t.uid)over(partition by t.tag)as cnt
from (select er.uid,ef.tag,(sum(if(submit_time is null,1,0))/count(start_time)) as f_rote
from exam_record er left join examination_info ef 
on ef.exam_id=er.exam_id 
where tag='SQL' 
group by uid ) t)select  #第四步,分用户和月份进行数据统计;同时需要注意,统计的试卷数是所有类型的,不是之前仅有SQL类型uid,start_month,count(start_time) as total_cnt,count(submit_time) as complete_cnt
from 
(
select # 第三步,利用窗口函数对每个用户的月份进行降序排序,以便找出最近的三个月;uid,start_time,submit_time,date_format(start_time,'%Y%m') as start_month,dense_rank()over(partition by uid order by date_format(start_time,'%Y%m') desc) as rank3
from exam_record 
where uid in (select distinct er.uidfrom exam_record er left join user_info uf on uf.uid=er.uidwhere er.uid in (select uid from rote_tab #引用公用表 rote_tabwhere rank2<=round(cnt/2,0))and uf.level in (6,7))  # 第二步,进一步找出满足等级为6或7的用户ID
) t2
where rank3<=3
group by uid,start_month
order by uid,start_month

2聚合窗口函数

2.1 对试卷得分做min-max归一化

我的报错代码:(得分区间默认为[0,100],如果某个试卷作答记录中只有一个得分,那么无需使用公式,归一化并缩放后分数仍为原分数)这个怎么筛选出去呀

select er.uid,er.exam_id,
(score-min(score))/(max(score)-min(score)) avg_new_score
from examination_info ei join exam_record er
using(exam_id)
where difficulty = 'hard'
group by er.uid,er.exam_id
order by er.uid desc,avg_new_score desc

 大佬代码:

# 第一步先求出高难度试卷的最值max_min_tab
with max_min_tab as 
(select  er.uid,er.exam_id,er.score,max(er.score)over(partition by er.exam_id) as max_score,min(er.score)over(partition by er.exam_id) as min_score
from exam_record er 
left join examination_info ef on er.exam_id=ef.exam_id
where score is not null and difficulty='hard')select uid,exam_id, #第三步进行取平均值和排序
round(avg(new_score)) as avg_new_score
from 
(select uid,exam_id
,if(max_score!=min_score,(score-min_score)/(max_score-min_score)*100,score) as new_score
from max_min_tab) t  # 第二步在max_min_tab中进行归一化计算,并用if排除只有一个分数的
group by exam_id,uid
order by exam_id,avg_new_score desc

复盘:

(1)最值窗口函数:不是直接max,min再后面分组

max(er.score)over(partition by er.exam_id) as max_score,

min(er.score)over(partition by er.exam_id) as min_score

(2)用if来排除只有一个分数的情况

if(max_score!=min_score,(score-min_score)/(max_score-min_score)*100,score

2.2每份试卷每月作答数和截止当月的作答总数。

我的代码:

select exam_id,
date_format(submit_time,"%Y%m") start_month,
count(submit_time)over(partition by exam_id) month_cnt,
count(submit_time)over(partition by exam_id) cum_exam_cnt #应该要用偏移分析函数
from exam_record

 大佬代码:

select distinct exam_id,
date_format(start_time,'%Y%m') start_month,
count(start_time)over(partition by exam_id,date_format(start_time,"%Y%m")) month_cnt,
count(start_time)over(partition by exam_id order by date_format(start_time,'%Y%m')) cum_exam_cnt 
from exam_record
order by exam_id,start_month

复盘:

(1)要distinct exam_id,如果不去重 exam_id,那么同 exam_id和同月会被输出原文件中exam_id和同月配套出现那么多次。

如:

又如:

(2)是start_time而不是submit_time,start_time有记录才表明有作答

2.3 每月及截止当月的答题情况

我的代码:后面三个没有整出来

select 
distinct date_format(start_time,'%Y%m') start_month,
count(uid)over(partition by date_format(start_time,'%Y%m')) mau,
# if(count>0,count,0) month_add_uv,
# max(month_add_uv)over(partition by date_format(start_time,'%Y%m')) max_month_add_uv,
# max(mau)over() cum_sum_uv
from exam_record
group by uid,start_month
order by start_month

大佬代码:

select start_month
, count(distinct uid) as mau
, count(if(rn=1, uid, null)) as month_add_uv
, max(count(if(rn=1, uid, null))) over(order by start_month) as max_month_add_uv
, sum(count(if(rn=1, uid, null))) over(order by start_month) as cum_sum_uv
from (selectuid, date_format(start_time, '%Y%m') as start_month, row_number() over(partition by uid order by start_time) as rnfrom exam_record
) t
group by start_month
;

复盘:

(1)【排序窗口函数】

●   rank()over()——1,1,3,4

●   dense_rank()over()——1,1,2,3

●   row_number()over()——1,2,3,4

这里使用 row_number()over()就只有一个1,那么如果uid有排名为1的,就表示是这个月的新用户。

(2)

  • SQL查询语句语法结构和运行顺序
    • 运行顺序:from--where--group by--having--order by--limit--select
    • 语法结构:select--from--where--group by--having--order by--limit

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

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

相关文章

Xamarin.Android实现通知推送功能(1)

目录 1、背景说明1.1 开发环境1.2 实现效果1.2.1 推送的界面1.2.2 推送的设置1.2.3 推送的功能实现1.2.3.1、Activity的设置【重要】1.2.3.2、代码的实现 2、源码下载3、总结4、参考资料 1、背景说明 在App开发中&#xff0c;通知&#xff08;或消息&#xff09;的推送&#x…

HTML美观的搜索框怎么做?

一、“融情于景”1.0 <form action"" class"search-bar"><input type"search" name"search" pattern".*\S.*" required><button class"search-btn" type"submit"><span>Searc…

​​​​​​ 基于Nmap的异步无状态端口扫描技术

​​​​​​ 基于Nmap的异步无状态端口扫描技术 传统的端口扫描&#xff0c;主要是依靠TCP三次握手去连接&#xff0c;而建立连接的各个过程都存在连接状态&#xff0c;这些状态由操作系统在底层实现存储&#xff0c;可利用这些状态对应用层的数据进行处理。但是&#xff0c;…

企业必备技能-打造全屏轮播图的终极指南

标题&#xff1a;“视觉盛宴&#xff1a;打造全屏轮播图的终极指南” 引言 在网页设计中&#xff0c;轮播图是一种常见的视觉元素&#xff0c;它能够吸引访客的注意力并展示重要内容。本文档将指导你如何使用HTML和CSS快速创建一个全屏轮播图&#xff0c;使您的网站更加生动和…

算法学习笔记(7.4)-贪心算法(区间调度问题)

目录 ##什么是区间调度问题 ##贪心解法 ##具体的例题示例讲解 ##452. 用最少数量的箭引爆气球 - 力扣&#xff08;LeetCode&#xff09; ##435. 无重叠区间 - 力扣&#xff08;LeetCode&#xff09; ##56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; ##什么是区间调…

毫米波雷达深度学习技术-1.6目标识别2

1.6.4 自动编码器和变体自动编码器 自编码器包括一个编码器神经网络&#xff0c;随后是一个解码器神经网络&#xff0c;其目的是在输出处重建输入数据。自动编码器的设计在网络中施加了一个瓶颈&#xff0c;它鼓励原始输入的压缩表示。通常&#xff0c;自编码器旨在利用数据中的…

学习周报:文献阅读+Fluent案例+Fluent相关算法学习

目录 摘要 Abstract 文献阅读&#xff1a;求解正逆运动波问题的物理信息神经网络 文献摘要 讨论|结论 理论基础 KWM&#xff08;运动波动方程&#xff09; Hard constraint &#xff08;硬约束方式&#xff09; 具有重新分布的搭配点的PINN 具有停止梯度的分数阶方程 …

实验二、网络属性设置《计算机网络》

精神状态 be like&#xff1a;边写边崩溃&#xff0c;越写越得劲儿。 目录 一、实验目的&#xff1a; 二、实验内容 三、实验步骤&#xff1a; 四、实验小结 一、实验目的&#xff1a; 掌握 IP 地址、子网掩码等网络属性的设置。 二、实验内容 预备知识&#xff1a; 1、…

【leetcode--统计优美子数组】

解题思路 一、滑动窗口 不断右移 right 指针来扩大滑动窗口&#xff0c;使其包含 k 个奇数&#xff1b; 若当前滑动窗口包含了 k 个奇数&#xff0c;则如下「计算当前窗口的优美子数组个数」&#xff1a; 统计第 1 个奇数左边的偶数个数 leftEvenCnt。 这 leftEvenCnt 个偶数…

代码随想录算法训练营第30天|回溯

回溯part06 332. 重新安排行程 写了好长时间&#xff0c;最后超时了qaq /*** param {string[][]} tickets* return {string[]}*///ticket[1] [2,3]表示航线1是从地点2飞到地点3的 //所有机票必须用过一次 //优先选取字典排序更小的行程 var findItinerary function(ticket…

耐酸碱腐蚀可溶性聚四氟乙烯(PFA)溶样罐

PFA溶样罐也叫PFA溶样瓶&#xff0c;可直接放在加热板上及油浴里加热&#xff0c;也可液氮下长期保存&#xff0c;使用温度-200—260℃。 根据不同实验的需求&#xff0c;PFA溶样罐有U型、V型、平底3种设计。V型底的设计&#xff0c;更加方便少量样品的集中收集。溶样罐广泛用…

Java 实验8 集合类

&#xff08;一&#xff09;实验目的 1、掌握JAVA集合类中的Collection的特点及其应用情形&#xff1b; 3、掌握Collection、熟悉集合的特点及应用。 &#xff08;二&#xff09;实验内容和步骤 1、仿照课堂练习的MyStack示例&#xff0c;使用LinkedList集合类实现一个先进…

Jira的原理及应用详解(三)

本系列文章简介: 在当今快速发展的软件开发和项目管理领域,有效的团队协作和精确的项目进度追踪是确保项目成功的关键。Jira作为一款广受欢迎的项目和问题追踪工具,以其强大的功能、灵活的定制性以及卓越的用户体验,赢得了全球众多企业的青睐。 Jira最初由Atlassian公司开发…

MTK默认开启Modem Log

基于Android12&#xff0c;user默认开启Modem Log。 修改分为三部分&#xff1a; 1.config修改 --- a/alps/device/mediatek/common/mtklog/mtklog-config-basic-user.propb/alps/device/mediatek/common/mtklog/mtklog-config-basic-user.prop-3,12 3,12 mtklog_path sys…

采购管理软件怎么选才不踩坑?收下这14 步清单

自动化采购任务和优化从采购到付款的周期可以为企业节省大量的资金和时间。但采用过时的采购方法&#xff08;基于纸张的系统或 excel 电子表格&#xff09;&#xff0c;不可能获得这些好处。 采购管理软件之所以重要&#xff0c;是因为它为企业提供了有效跟踪、管理和分析支出…

DolphinScheduler调度系统

Apache DolphinScheduler 是一个开源的调度系统。它是一个分布式、大数据工作流调度系统&#xff0c;专门为数据工程师、数据科学家和数据分析师设计&#xff0c;提供了丰富的功能来管理和调度大数据处理任务。以下是关于 Apache DolphinScheduler 的一些关键点&#xff1a; 主…

数据库管理工具——DBeaver简介

在数据库管理的世界里&#xff0c;选择一个高效、稳定且易于使用的工具至关重要。今天&#xff0c;我将为大家介绍一款备受好评的数据库管理工具——DBeaver&#xff0c;并详细讲解其使用方法。 一、DBeaver简介 DBeaver是一个基于Java的开源数据库管理工具&#xff0c;支持几…

探索多头混合专家(MH-MoE)模型的先进架构

在深度学习领域&#xff0c;大型模型如大型语言模型&#xff08;LLMs&#xff09;和大型多模态模型&#xff08;LMMs&#xff09;因其在各个领域的有效性而受到广泛关注。然而&#xff0c;这些模型在训练和推理时面临着巨大的计算成本。为了解决这一问题&#xff0c;研究者们提…

多分类混淆矩阵详解

⭐️ 前言 在机器学习和数据科学中&#xff0c;混淆矩阵&#xff08;Confusion Matrix&#xff09;是一个重要的工具&#xff0c;用于评估分类模型的性能。特别是在多分类问题中&#xff0c;混淆矩阵能够清晰地展示模型在每个类别上的预测结果。以下是对多分类混淆矩阵的详细解…

IDEA下项目发送到Gitee

一、首先在Gitee创建一个仓库&#xff08;什么都不选&#xff0c;这是最简单的方式&#xff0c;否则需要 pull push等一些操作&#xff0c;我嫌麻烦&#xff09; 二、按图点击&#xff08;创建存储区&#xff0c;选择你要上传的项目&#xff09; 三、按图点击后正常文件名会变绿…