题解 | #SQL 12.连续签到领金币#

连续签到领金币

http://www.nowcoder.com/practice/aef5adcef574468c82659e8911bb297f

连续签到领金币

明确题意:

计算每个用户2021年7月以来每月获得的金币数(该活动到10月底结束,11月1日开始的签到不再获得金币),结果按月份、ID升序排序。


问题分解:

  • 计算每个人连续签到的天次(生成子表t_sign_idx):
    • 计算每次签到的序号和连续签到起始日期(生成子表t_sign_base):
      • 计算每次签到的序号(生成子表t_sign_date_rn):
        • 过滤出活动期内的有效签到记录:
          • 有效签到:artical_id = 0 and sign_in = 1
          • 活动期:DATE(in_time) >= "2021-07-07" and DATE(in_time) <= "2021-10-31"
        • 截取签到日期:DATE(in_time) as sign_dt
        • 每次签到序号(按天,相同日期的序号一样):DENSE_RANK() over(partition by uid order by DATE(in_time)) as rn
        • 去重,每天的多次签到只保留一条:SELECT DISTINCT uid, sign_dt, rn
      • 计算当前签到往前连续的起始日期:DATE_SUB(sign_dt, INTERVAL rn DAY) as base_dt
    • 定义窗口,按每个用户每次起始日期分区,按签到日期排序:window wd_uid_dt as (partition by uid, base_dt order by sign_dt)
    • 计算当前签到是一个签到周期内(7天一个周期)的连续签到的天序:(ROW_NUMBER() over(wd_uid_dt) - 1) % 7 as sign_idx
  • 按用户和月份分组:group by uid, DATE_FORMAT(sign_dt, "%Y%m")
  • 计算每个用户每月获取的金币:
    • 第3天和第7天单独奖励,其他为1:case when sign_idx=6 then 7 when sign_idx=2 then 3 else 1 end
    • 计算总金币,求和:sum()

细节问题:

  • 表头重命名:as
  • 按月份、ID升序排序:order by month, uid;

完整代码:

select uid, DATE_FORMAT(sign_dt, "%Y%m") as `month`,
    sum(case when sign_idx=6 then 7 when sign_idx=2 then 3 else 1 end) as coin
from (
    select uid, sign_dt,
        (ROW_NUMBER() over(wd_uid_dt) - 1) % 7 as sign_idx
    from (
        select uid, sign_dt, rn, DATE_SUB(sign_dt, INTERVAL rn DAY) as base_dt
        from (
            select DISTINCT uid, DATE(in_time) as sign_dt,
                DENSE_RANK() over(partition by uid order by DATE(in_time)) as rn
            from tb_user_log
            where artical_id = 0 and sign_in = 1 
                and DATE(in_time) >= "2021-07-07" and DATE(in_time) <= "2021-10-31"
        ) as t_sign_date_rn
    ) as t_sign_base
    window wd_uid_dt as (partition by uid, base_dt order by sign_dt)
) as t_sign_idx
group by uid, `month`
order by `month`, uid;
SQL大厂真题 文章被收录于专栏

大厂真题手把手教你怎么解~

全部评论
大佬请问一下定义窗口 window 的用法
3 回复 分享
发布于 2021-12-22 15:12
(ROW_NUMBER() over(wd_uid_dt) - 1) % 7 as sign_idx 中的wd_uid_dt 哪来的,找不到啊
点赞 回复 分享
发布于 2022-01-27 12:38
大佬请问下为啥(ROW_NUMBER() over(wd_uid_dt) - 1) % 7 as sign_idx里面要-1呢
点赞 回复 分享
发布于 2022-02-20 21:57
再次看见大佬,respect
点赞 回复 分享
发布于 2022-05-05 18:55

相关推荐

09-14 14:42
门头沟学院 C++
旺旺米雪饼:举办了哥,你什么都没做错,全怪我那令人作呕的嫉妒和卑微的自尊心,看见你的文字我完全破防了,我直接丢盔弃甲了,看见你这图的那一秒,我满头大汗,浑身发冷,亿郁症瞬间发作了,生活仿佛没了颜色,像是被抓住尾巴的赛亚人,带着海楼石的能力者,抽离尾兽的人柱力,像是没了光的奥特曼,彻底断绝了生的希望。我几乎都快羡慕得疯了,倒在床上蒙住被子就开始抱着枕头尖叫流泪,嘴里一边喊着卧槽卧槽,一边又忍着,我边发边哭,打字的手都是抖的,后来我的手抖得越来越厉害,从心头涌起的思想、情怀和梦想,这份歆羡和悔恨交织在一起,我的笑还挂在脸上,可是眼泪一下子就掉下来了。求你了别发了,我生活再难再穷我都不会觉得难过,只有你们发这种东西的时候,我的心里像被刀割一样的痛,打着字泪水就忍不住的往下流。每天早上6点起床晚上11点睡觉,年复一年地学到现在,憧憬着一个月赚上万块的幸福生活,憧憬着美好阳光的未来。我打开了手机,看到你的图,我感到了深深的差距,我直接跳进了家门口的井里😭😭😭我真的😭我要嫉妒疯了😭为什么!!为什么这个人不是我😡我求你了😭求你了😭!不要在发了,我真的要羡慕嫉妒疯了😱怎么办我要嫉妒死了啊啊啊啊我急了,手机电脑全砸了,本来就有抑郁症的我,被别人说我破防了,我真的恼羞成怒了,仿佛被看穿了,躲在网络背后的我,这种感觉真的好难受,我被看穿的死死地,短短的破防两个字,我伪装出来的所有的坚强和强颜欢笑全都崩塌了,成了一个被人笑话的小丑🤡,我真的不想再故作坚强了,玩心态我输的什么都不剩😭😭😭
点赞 评论 收藏
分享
去B座二楼砸水泥地:不过也可以理解,这种应该没参加过秋招
点赞 评论 收藏
分享
14 2 评论
分享
牛客网
牛客企业服务