题解 | #连续签到领金币#
连续签到领金币
https://www.nowcoder.com/practice/aef5adcef574468c82659e8911bb297f
# 1. 筛选出各用户符合条件的签到日期,得到<签到表> SELECT * FROM tb_user_log where date(in_time) between '2021-07-07' and '2021-10-31' and artical_id=0 and sign_in=1;
# 2. 对签到表进行排序。使用窗口函数row_number() # 以uid分组 # 按照date(in_time)排序 SELECT uid, date(in_time) dt, row_number() over (partition by uid order by date(in_time)) ranking FROM tb_user_log where date(in_time) between '2021-07-07' and '2021-10-31' and artical_id=0 and sign_in=1;
# 3. 求出各用户连续登录的天数 #(1)用(dt-ranking)得到日期dt2,如果是连续签到,则dt2的日期相同 SELECT uid, date(in_time) dt, row_number() over (partition by uid order by date(in_time)) ranking, date(in_time)-(row_number() over (partition by uid order by date(in_time))) dt2 FROM tb_user_log where date(in_time) between '2021-07-07' and '2021-10-31' and artical_id=0 and sign_in=1;
#(2)再来计算日期对应的连续签到天数 select *, row_number() over(PARTITION BY t1.uid,t1.dt2 order by t1.dt) ranking2 # 窗口的partition分组根据uid和差值日期dt2 FROM ( SELECT uid, date(in_time) dt, row_number() over (partition by uid order by date(in_time)) ranking, date(in_time)-(row_number() over (partition by uid order by date(in_time))) dt2 FROM tb_user_log where date(in_time) between '2021-07-07' and '2021-10-31' and artical_id=0 and sign_in=1 )t1 ;
#(3)有了连续签到天数ranking2,就可以攻克每日领取的金币数量了,取7的余数,用case when来判断范围。 select *, row_number() over(PARTITION BY t1.uid,t1.dt2 order by t1.dt) ranking2, case when row_number() over(PARTITION BY t1.uid,t1.dt2 order by t1.dt)%7=3 then 3 when row_number() over(PARTITION BY t1.uid,t1.dt2 order by t1.dt)%7=0 then 7 else 1 end coin FROM ( SELECT uid, date(in_time) dt, row_number() over (partition by uid order by date(in_time)) ranking, date(in_time)-(row_number() over (partition by uid order by date(in_time))) dt2 FROM tb_user_log where date(in_time) between '2021-07-07' and '2021-10-31' and artical_id=0 and sign_in=1 ) t1 ;
# 4. 整理格式,按照uid,月份分组,求出对应的coin和。并且按照月份、ID升序排序 select t2.uid, DATE_FORMAT(t2.dt,'%Y%m') month, sum(t2.coin) coin FROM ( select *, row_number() over(PARTITION BY t1.uid,t1.dt2 order by t1.dt) ranking2, case when row_number() over(PARTITION BY t1.uid,t1.dt2 order by t1.dt)%7=3 then 3 when row_number() over(PARTITION BY t1.uid,t1.dt2 order by t1.dt)%7=0 then 7 else 1 end coin FROM ( SELECT uid, date(in_time) dt, row_number() over (partition by uid order by date(in_time)) ranking, date(in_time)-(row_number() over (partition by uid order by date(in_time))) dt2 FROM tb_user_log where date(in_time) between '2021-07-07' and '2021-10-31' and artical_id=0 and sign_in=1 )t1 )t2 group by t2.uid, DATE_FORMAT(t2.dt,'%Y%m') order by t2.uid, DATE_FORMAT(t2.dt,'%Y%m') ;