文章目录
- 题目需求
- 思路一
- 实现一
- 题目来源
题目需求
用户每天签到可以领1金币,并可以累计签到天数,连续签到的第3、7天分别可以额外领2和6金币。
每连续签到7天重新累积签到天数。
从用户登录明细表中求出每个用户金币总数,并按照金币总数倒序排序。
期望结果如下(截取部分):
user_id (用户id) | sum_coin_cn (金币总数) |
---|---|
101 | 7 |
109 | 3 |
107 | 3 |
需要用到的表:
用户登录明细表:user_login_detail
user_id(用户id) | ip_address(ip地址) | login_ts(登录时间) | logout_ts(登出时间) |
---|---|---|---|
101 | 180.149.130.161 | 2021-09-21 08:00:00 | 2021-09-27 08:30:00 |
102 | 120.245.11.2 | 2021-09-22 09:00:00 | 2021-09-27 09:30:00 |
103 | 27.184.97.3 | 2021-09-23 10:00:00 | 2021-09-27 10:30:00 |
思路一
实现一
-- 4) 计算每个用户应得的总金币数
select user_id,
login_days + sum(external_coin) as sum_coin_cn
from (
-- 3) 计算每个用户 每次的连续登录数据
select user_id,
login_days,
-- 本次连续登录天数
count(*) as every_max_continuous_login_days,
-- 计算本次连续应额外领多少金币
-- 计算逻辑见思路一
if(count(*) >= 3, 2 * (cast((count(*) - 3) / 7 as int) + 1) + 6 * cast((count(*) / 7) as int),
0) as external_coin
from (
-- 2) 计算每个用户 每次的连续登录数据-中间过度步骤(参考: https://blog.csdn.net/weixin_43676735/article/details/131458344 实现一)
select user_id,
login_days,
date_add(login_ts_format,
-row_number() over (partition by user_id order by login_ts_format)) as sub_res
from (
-- 1) 对用户每天的登录进行去重
select user_id,
date_format(login_ts, 'yyyy-MM-dd') as login_ts_format,
-- 计算该用户总共的登录天数,用于用户每天领1金币
count(*) over (partition by user_id) as login_days
from user_login_detail
group by user_id, date_format(login_ts, 'yyyy-MM-dd')
) t1
) t2
group by user_id, sub_res, login_days
) t3
group by user_id, login_days
order by sum_coin_cn desc;
题目来源
http://practice.atguigu.cn/#/question/38/desc?qType=SQL