简单的签到代码_开窗排序函数解决连续签到问题|SQL

开窗排序函数除了在处理简单的排序问题外,它的应用场景远比我们想的要多。本文将对两个问题,介绍开窗排序函数的用法。

一、问题

有一张用户签到表【签到表】,标记每天用户是否签到(说明:该表包含所有用户所有工作日的出勤记录) ,包含三个字段:日期【a_date】,用户id【a_id】,是否签到【fis_sign_in】。

问题1:用户最近一次连续签到的天数?
输出表:用户id【a_id】,用户连续签到天数【最近连续签到天数】

问题2:用户最大连续签到天数?

输出表:用户id【a_id】,用户最大连续签到天数【最大连续签到天数】

二、数据集的理解:连续签到问题的数据集分为两种

1、只包含用户签到的日期,用户没有签到的数据不做记录;

2、包含所有工作日的记录,其中有设置字段来记录用户是否签到(例如字段fis_sign _in,0为未签到,1为已签到)。

但第二种数据集的处理很简单,只要在第一种的基础上筛选掉 fis_sign_in=0 就可以了。

二、思路

如果是连续的几天,那么它们日期分别减去排序后的值是相同的,注意这里的排序是连续的。

假设日期为a,a+1,a+2,排名为1,2,3,那么日期分别减去排序的值都为a-1;

假设日期为b,b+2,b+3,排名为,1,2,3,那么日期分别减去排序的值为b-1,b。

be180bbba4b0ecad7c906333252d0b16.png

但要注意的是!如果数据集含有不同月份的数据,日期不能只是简单的减去排序,因为如果把月份看作数值,那么不同月份之间的数值并不是连续的,比‘2020-03-31’和‘2020-04-01’在数值上就不是连续的,那么在减去连续的排序后,它们的值是不相等的,因此不会把他们归为同一类。

如图前两行:

65a9017dc423ec3393c356d6605ec8b4.png

因此我们要做一个处理,让处理后的rankk还是以日期的形式保留。我们可以在日期列上减去“排序”个天数,这样返回的rankk列就是以日期形式保留了。

date_add(日期, interval -排序 day)
date_add(a_date,interval-(row_number() over (partition by a_id order by a_date))day)

连续签到天数的代码:

分组前:
select a_id,a_date,
date_add(a_date,interval-(row_number() over (partition by a_id order by a_date))day)
as rankk
from 签到表;

分组后:
create view 连续签到表 as
select a_id,max(a_date)as 最后一次签到日期,count(*)as 连续签到天数 from 
(select a_id,a_date,
date_add(a_date,interval-(row_number() over (partition by a_id order by a_date))day)
as rankk
from 签到表) as s1
group by a_id,rankk

aebb8e1f424318638e5b6de12447bdc1.png
签到表

c90971609e8462280bcb784594b6bc68.png
分组后:连续签到表

三、答案

问题1:用户最近一次连续签到的天数?/用户截止今天的连续签到天数?
输出:用户id【id】,用户连续签到天数【最近连续签到天数】

在连续签到基础上,利用关联子查询,找出各用户最后一次签到日期的最大值即可。

select a_id,连续签到天数 as 最近连续签到天数
from 连续签到表 as s1
where 最后一次签到日期>=ALL
(select 最后一次签到日期 from 连续签到表 as s2
where s1.a_id=s2.a_id
group by a_id)

65cc37598d085a8e6a72279be856bcd0.png

问题2:用户最大连续签到天数?

输出表:用户id【id】,用户最大连续签到天数【最大连续签到天数】

在连续签到基础上,取出max(连续签到天数)

select a_id,max(连续签到天数) as 最大连续签到天数
from 连续签到表
group by a_id;

425ba2e20a40787dac57a1b9342a64e9.png

如果数据集属于第二种数据集,只需在建立连续签到表处添加where fis_sign_in=1即可。

ac30a4fd5e0102a9f8dc47850d5f8b6e.png
create view 连续签到表 as
select a_id,max(a_date)as 最后一次签到日期,count(*)as 连续签到天数 from 
(select a_id,a_date,
date_add(a_date,interval-(row_number() over (partition by a_id order by a_date))day)
as rankk
from 签到表
where fis_sign_in=1) as s1
group by a_id,rankk

ae98128a4c595e690002970657255372.png

d65d771a389334148e545e6b30f15c9c.png

4981f1f270acb0f7cfb3efb24b1dfe1c.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值