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) a

inner 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_time
    from exam_record
    where 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 ranking
    from 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.uid
    from exam_record er left join user_info uf on uf.uid=er.uid
    where er.uid in 
    (select uid from rote_tab #引用公用表 rote_tab
    where 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 (
    select
      uid, date_format(start_time, '%Y%m') as start_month
    , row_number() over(partition by uid order by start_time) as rn
    from 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

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

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

相关文章

m3u8视频怎么打开?教你三招!

m3u8 是一种文本文件格式&#xff0c;用于创建媒体播放列表&#xff0c;现在大部分的视频流媒体都是m3u8格式。当我们从网上下载下来m3u8文件的时候会发现&#xff0c;它本身不是一段视频&#xff0c;而是一个索引纯文本文件。想要正常打开播放m3u8视频其实也很简单&#xff0c…

解码 LangChain | LangChain + GPTCache =兼具低成本与高性能的 LLM

LangChain 联合创始人 Harrison Chase 提到&#xff0c;多跳问题会给语义检索带来挑战&#xff0c;并提出可以试用 AI 代理工具解决。不过&#xff0c;频繁调用 LLM 会导致出现使用成本高昂的问题。 对此&#xff0c;Zilliz 软件工程师 Filip Haltmayer 指出&#xff0c;将 GP…

塑造财务规划团队的未来角色

随着企业不断改革&#xff0c;其财务规划团队的格局也在不断变化&#xff0c;领先行业的专业人士已经开始利用更创新的财务知识和思维来驾驭现代化财务规划角色的复杂性。财务团队需要不同的职能角色和技能组合来支持其发展&#xff0c;多学科团队和跨职能协作带来的挑战和机遇…

C语言详解(动态内存管理)1

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

MacBook Pro上高cpu上不断重启运行的efilogin-helper

高 cpu 运行这个不知道干什么的进程&#xff0c;让风扇疯狂输出&#xff0c;让人甚是烦躁&#xff0c;苹果社区里的回答比较抽象&#xff0c;要么换设备&#xff0c;要么重装。 尝试过找到这个文件&#xff0c;删了部分内容&#xff0c;无果。。。 stack overflow 有个回答&a…

stm32驱动直流电机实现启动/加速/减速/倒车/停车等功能

不积跬步&#xff0c;无以至千里&#xff1b;不积小流&#xff0c;无以成江海。 大家好&#xff0c;我是闲鹤&#xff0c;公众号 xxh_zone&#xff0c;十多年开发、架构经验&#xff0c;先后在华为、迅雷服役过&#xff0c;也在高校从事教学3年&#xff1b;目前已创业了7年多&a…

UML交互图-协作图

概述 协作图和序列图都表示出了对象间的交互作用&#xff0c;但是它们侧重点不同。序列图清楚地表示了交互作用中的时间顺序&#xff0c;但没有明确表示对象间的关系。协作图则清楚地表示了对象间的关系&#xff0c;但时间顺序必须从顺序号获得。序列图常常用于表示方案&#…

使用紫铜管制作半波天线的折合振子

一、概述 半波天线是一种简单而有效的天线类型&#xff0c;其长度约为工作波长的一半。它具有较好的辐射特性和较高的增益&#xff0c;广泛应用于业余无线电、电视接收等领域。使用紫铜管制作折合振子&#xff0c;不仅可以提高天线的机械强度&#xff0c;还能增强其导电性能。 …

k8s——Pod容器中的存储方式及PV、PVC

一、Pod容器中的存储方式 需要存储方式前提&#xff1a;容器磁盘上的文件的生命周期是短暂的&#xff0c;这就使得在容器中运行重要应用时会出现一些问题。 首先&#xff0c;当容器崩溃时&#xff0c;kubelet 会重启它&#xff0c;但是容器中的文件将丢失——容器以干净的状态&…

如何让tracert命令的显示信息显示*星号

tracert命令如果在中间某一个节点超时&#xff0c;只会在显示信息中标识此节点信息超时“ * * * ”&#xff0c;不影响整个tracert命令操作。 如上图所示&#xff0c;在DeviceA上执行tracert 10.1.2.2命令&#xff0c;缺省情况下&#xff0c;DeviceA上的显示信息为&#xff1a;…

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…

k8s小型实验模拟

&#xff08;1&#xff09;Kubernetes 区域可采用 Kubeadm 方式进行安装。&#xff08;5分&#xff09; &#xff08;2&#xff09;要求在 Kubernetes 环境中&#xff0c;通过yaml文件的方式&#xff0c;创建2个Nginx Pod分别放置在两个不同的节点上&#xff0c;Pod使用hostPat…

Gradio 案例——将文本文件转为词云图

文章目录 Gradio 案例——将文本文件转为词云图界面截图依赖安装项目目录结构代码 Gradio 案例——将文本文件转为词云图 利用 word_cloud 库&#xff0c;将文本文件转为词云图更完整、丰富的示例项目见 GitHub - AlionSSS/wordcloud-webui: The web UI for word_cloud(text t…

AI产品经理岗位需求量大吗?好找工作吗?

前言 在当今这个科技日新月异的时代&#xff0c;人工智能&#xff08;AI&#xff09;已不再仅仅是一个遥远的概念&#xff0c;而是深深嵌入到我们生活的方方面面&#xff0c;从日常的语音助手到复杂的自动驾驶系统&#xff0c;AI的触角无处不在。随着AI技术的广泛应用和持续进…

kettle列转行(行扁平化)的使用

kettle行扁平化节点是将多行数据合并为一行数据如&#xff0c;其行为类似于css中的float排列 将上表格数据转换为下表格数据 namecategorynumjack语文10jack数学20jack英语40rose英语50 name语文数学英语jack102040rose50 使用行扁平化节点配置需要扁平化的字段&#xff0c…

泛微开发修炼之旅--09Ecology作为所有异构系统的待办中心,实现与kafka对接源码及示例

文章链接&#xff1a;泛微开发修炼之旅--09Ecology作为所有异构系统的待办中心&#xff0c;实现与kafka对接源码及示例

龙迅LT6911GX HDMI 2.1桥接到四 PORT MIPI或者LVDS,支持图像处理以及旋转,内置MCU以及LPDDR4

龙迅LT6911GX描述&#xff1a; LT6911GX是一款高性能的HDMI2.1到MIPI或LVDS芯片&#xff0c;用于VR/显示器应用。HDCP RX作为HDCP中继器的上游端&#xff0c;可以与其他芯片的HDCP TX协同工作&#xff0c;实现中继器的功能。对于HDMI2.1输入&#xff0c;LT6911GX可配置为3/4车…

JavaScript的核心语法

JavaScript JavaScript&#xff1a;JavaScript的组成&#xff1a;核心语法&#xff1a;Hello&#xff1a;变量&#xff1a;JS的基本数据类型&#xff1a;特殊点&#xff1a; 数组&#xff1a;流程控制语句&#xff1a;函数&#xff1a;函数的重载&#xff1a;函数的递归:预定义…

python-windows10普通笔记本跑bert mrpc数据样例0.1.001

python-windows10普通笔记本跑bert mrpc数据样例0.1.000 背景参考章节获取数据下载bert模型下载bert代码windows10的cpu执行结果注意事项TODOLIST背景 看了介绍说可以在gpu或者tpu上去微调,当前没环境,所以先在windows10上跑一跑,看是否能顺利进行,目标就是训练的过程中没…

WWDC24即将到来,ios18放大招

苹果公司即将在下周开全球开发者大会(WWDC)&#xff0c;大会上将展示其人工智能技术整合到设备和软件中的重大进展,包括与OpenAI的历史性合作。随着大会的临近,有关iOS 18及其据称采用AI技术支持的应用程序和功能的各种泄露信息已经浮出水面。 据报道,苹果将利用其自主研发的大…