题解 | #连续签到领金币# 解题思路总结

连续签到领金币

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

题目分析

比较好理解的思考方式是根据需要的结果,一步一步反推自己需要什么的格式的数据

  1. 要求活动期间的签到获得的金币总数,那我最希望的是能够获得每一天用户签到时获得的金币数,然后只需要按照ID和month分组,sum一下就可以,如图

alt

  1. 再反推,想要获得每一天用户签到时获得的金币数,那么我必须知道,用户当天签到是连续签到的第几天,得到天数以后很简单了,用case when 将天数 % 7 ,看余数。 余数是3 ,当天获得 3枚。余数是 0 ,当天获得7枚 。其他为 1 枚 。如图

alt

  1. 推到这里那其实思路已经清晰了,求连续签到的天数,那无非就是连续问题

    1. 连续问题核心就是利用排序编号与签到日期的差值是相等的。因为如果是连续的话,编号也是自增1,日期也是自增1。

    2. 如图,dt是签到日期,dt_tmp是编号和签到日期的差值。可以发现 编号 8 是断了连续签到的,所以dt_tmp与前面的不相同

alt

  1. 那么再以dt_tmp和 uid 来分组,再dense_rank 一次,就可以获得连续签到的天数了。那么问题就解决了。

alt

完整SQL

WITH t1 AS( -- t1表筛选出活动期间内的数据,并且为了防止一天有多次签到活动,distinct 去重
	SELECT
		DISTINCT uid,
		DATE(in_time) dt,
		DENSE_RANK() over(PARTITION BY uid ORDER BY DATE(in_time)) rn -- 编号
	FROM
		tb_user_log
	WHERE
		DATE(in_time) BETWEEN '2021-07-07' AND '2021-10-31' AND artical_id = 0 AND sign_in = 1
),
t2 AS (
	SELECT
	*,
	DATE_SUB(dt,INTERVAL rn day) dt_tmp, 
	case DENSE_RANK() over(PARTITION BY DATE_SUB(dt,INTERVAL rn day),uid ORDER BY dt )%7 -- 再次编号
		WHEN 3 THEN 3
		WHEN 0 THEN 7
		ELSE 1
	END as day_coin -- 用户当天签到时应该获得的金币数
	FROM
	t1
)
	SELECT
		uid,DATE_FORMAT(dt,'%Y%m') `month`, sum(day_coin) coin  -- 总金币数
	FROM
		t2
	GROUP BY
		uid,DATE_FORMAT(dt,'%Y%m')
	ORDER BY
		DATE_FORMAT(dt,'%Y%m'),uid;
全部评论
请问3天%7怎么等于3?求指教
点赞 回复 分享
发布于 2022-05-01 15:42
woc,你聪明的让我想自杀
3 回复 分享
发布于 2023-02-07 18:51 湖北
奉上我的膝盖
2 回复 分享
发布于 2022-07-26 18:10
我滴妈呀 我啥时候有这种脑回路
2 回复 分享
发布于 2022-07-06 11:04
有个问题,解题方法是以in_time作为签到日期,如果out_time跨天了怎么办
1 回复 分享
发布于 2023-09-27 23:29 上海
谢谢大佬,受益匪浅
1 回复 分享
发布于 2023-09-06 00:05 上海
签到日期和自增数列的差值那一块太巧妙了
1 回复 分享
发布于 2023-06-13 11:15 重庆
怎么有这么聪明的人类
1 回复 分享
发布于 2023-03-21 11:10 宁夏
有什么方法可以更好的理解第二个排名吗 有点吃力
1 回复 分享
发布于 2022-11-08 17:18 上海
请务必收下我的膝盖
1 回复 分享
发布于 2022-06-23 16:11
t2 AS ( SELECT *, DATE_SUB(dt,INTERVAL rn day) dt_tmp, case DENSE_RANK() over(PARTITION BY DATE_SUB(dt,INTERVAL rn day),uid ORDER BY dt )%7 -- 再次编号 WHEN 3 THEN 3 WHEN 0 THEN 7 ELSE 1 END as day_coin -- 用户当天签到时应该获得的金币数 请问这里为什么用dense_rank. partition by DATE_SUB(dt,INTERVAL rn day), uid 之后不是得出的值是一样的吗?
1 回复 分享
发布于 2022-05-29 15:28
思路真是清晰明了,膜拜大佬~
1 回复 分享
发布于 2022-05-05 10:51
请问一下,如果第8天签到时间是连续前一天的,怎么体现从1开始计呀?题目中是第8天不连续的情况
1 回复 分享
发布于 2022-04-10 09:56
请问以上代码换row_number 效果是一样的?
1 回复 分享
发布于 2022-03-11 19:55
牛的
1 回复 分享
发布于 2022-03-10 14:23
第二次编号,窗口over里面partition by不应该是uid在前,datesub在后吗
点赞 回复 分享
发布于 2024-07-20 10:14 浙江
牛的大佬,dt-tmp真的是太妙了
点赞 回复 分享
发布于 2024-03-25 14:57 河南
写的太好了!!!
点赞 回复 分享
发布于 2024-03-23 17:39 新加坡
怒抽了我的GPT3.5两巴掌,说好的要取代人类的呢?
点赞 回复 分享
发布于 2023-06-26 17:58 福建
赞美大佬,真的很巧妙,收益良多。
点赞 回复 分享
发布于 2023-06-13 15:45 重庆

相关推荐

04-30 21:35
已编辑
长安大学 C++
晓沐咕咕咕:评论区没被女朋友好好对待过的计小将可真多。觉得可惜可以理解,毕竟一线大厂sp。但是骂楼主糊涂的大可不必,说什么会被社会毒打更是丢人。女朋友体制内生活有保障,读研女朋友还供着,都准备订婚了人家两情相悦,二线本地以后两口子日子美滋滋,哪轮到你一个一线城市房子都买不起的996清高计小将在这说人家傻😅
点赞 评论 收藏
分享
高斯林的信徒:问你有没有保底,好人啊,就差把这是kpi面告诉你了
点赞 评论 收藏
分享
评论
296
28
分享

创作者周榜

更多
牛客网
牛客企业服务