题解 | #连续签到领金币#

连续签到领金币

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

通过代码

select uid,
       date_format(time, '%Y%m') month,
       sum(coins)                coin
from (select uid,
             time,
             (case
                  when ranking2 % 7 = 3 then 3
                  when ranking2 % 7 = 0 then 7
                  else 1
                 end) coins
      from (SELECT uid,
                   time,
                   ROW_NUMBER() OVER (
                       PARTITION BY uid, DATE_SUB(time, INTERVAL ranking DAY)
                       ORDER BY time
                       ) AS ranking2
            from (SELECT uid,
                         date(in_time) time,
                         rank() over (
                             partition by uid
                             order by date(in_time)
                             )         ranking
                  FROM tb_user_log
                  where artical_id = 0
                    and sign_in = 1
                    and date(in_time) between '2021-07-07' and '2021-10-31') t) t1) t2
group by uid, month(time)

artical_id-文章ID代表用户浏览的文章的ID,特殊情况artical_id-文章ID为0表示用户在非文章内容页(比如App内的列表页、活动页等)。注意:只有artical_id为0时sign_in值才有效

2021年7月7日0点开始,用户每天签到可以领1金币,并可以开始累积签到天数,连续签到的第3、7天分别可额外领2、6金币

每连续签到7天后重新累积签到天数(即重置签到天数:连续第8天签到时记为新的一轮签到的第一天,领1金币)

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

好,我们首先来分析一下这个题到底要从一个什么样的表里得到答案:

uid在签到的这一天得到了多少金币

怎么知道uid连签多少天从而确定该uid当天签到得到的金币呢

首先我们把合适得日期给筛选出来

也就是

表1 uid在那些天签到是有用签到

SELECT uid,
     date(in_time) time,
     rank() over (
         partition by uid
         order by date(in_time)
         )         ranking
FROM tb_user_log
where artical_id = 0
  and sign_in = 1
  and date(in_time) between '2021-07-07' and '2021-10-31'

注:为什么这里要用rank列出来一行?因为下一层需要用这个来进行连续天数计算

alt

表2 连续天数计算

SELECT uid,
   time,
   ROW_NUMBER() OVER (
       PARTITION BY uid, DATE_SUB(time, INTERVAL ranking DAY)
       ORDER BY time
       ) AS ranking2
from (表1) t

比如102在10-01、10-02、10-03排序分别是1,2,3那么这几天日前减去排序就是0、0、0,而在10-05、10-06减去排序就是1、1

这样就达到了计算连续的效果因为我们需要计算连续天数,所以这里用now_number函数进行排序

alt

问题:如果一个人在同一天多次签到怎么办

答:喊前端人员回来加班改bug,,,

开个玩笑 我们直接在表1处 加一个distinct完事


表3 uid在签到的这一天得到了多少金币

select uid,
   time,
   (case
        when ranking2 % 7 = 3 then 3
        when ranking2 % 7 = 0 then 7
        else 1
       end) coins
from (表2) t1

alt

注:我在第一次计算的时候写成了:when ranking2 % 3 = 0 then 3 就造成了第六天签到也是3块钱,uid直接多赚两块钱,资本家痛失两块钱,这怎么能行呢?


最后一层sum order 结束没啥说了,总之这个题,真无敌,我感觉做会了这个,sql没啥能拦住我们的了(^_^)

一天一个Mysql 文章被收录于专栏

学习,一天一个mysql

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务