题解 | #计算用户的平均次日留存率#

计算用户的平均次日留存率

http://www.nowcoder.com/practice/126083961ae0415fbde061d7ebbde453

题解:计算用户的平均次日留存率

题目分析

所谓次日留存,指的是同一用户(在本题中则为同一设备,即device_id)在当天和第二天都进行刷题。注意,在这题我们不关心同一用户(设备)在这天答了什么题、答题结果如何,只关心他是否答题,因此对于这题来说存在重复的数据(如下图红框所示),需要使用 DISTINCT 去重alt

而次日留存率可以这样表示:

=次日留存率=\frac{去重的数据表中符合次日留存的条目数目}{去重的数据表中所有条目数目}

具体而言,使用两个子查询,查询出两个去重的数据表,并使用条件(q2.date应该是q1.date的后一天)进行筛选,如下所示(数据未显示完全,从左至右顺序,列表名为 q1.device_id, q1.date, q2.device_id, q2.date)

image-20211001151306254alt

因为使用的是q1左级联q2,所以q1的所有信息是显示的;而q2中只显示留存的信息,否则为null。

最后,分别统计q1.device_id 和 q2.device_id 作去重后的所有条目数和去重后的次日留存条目数,即可算出次日留存率。

具体实现

SELECT 
    COUNT(q2.device_id) / COUNT(q1.device_id) AS avg_ret 
FROM 
    (SELECT DISTINCT device_id, date FROM question_practice_detail)as q1
LEFT JOIN
    (SELECT DISTINCT device_id, date FROM question_practice_detail) AS q2
ON q1.device_id = q2.device_id AND q2.date = DATE_ADD(q1.date, interval 1 day)

注意,MySQL中 COUNT在对列进行计数时不统计值为 null的条目

全部评论
写的真好,思路清晰,代码简洁,不过我还是好一会才弄懂,,,说一下学习的知识点吧 1.DISTINCT:这个关键字要么不同,用就需要要放在select的最前面,对所有列去重;若有多个列,是对多个列的组合去重 2.COUNT:在对列进行计数时不统计值为 null的条目 3.LEFT JOIN:其实q1和q2查询出来的结果,用LEFT JOIN连接后,q1就表示不同日期(第一天)有做过题的信息,q2表示第二天有做过题的信息 4.第一天和第二天的确定:q2.date = DATE_ADD(q1.date, interval 1 day),一直不知道怎么处理这种信息,学习了
29 回复 分享
发布于 2022-02-27 16:16
我咋看不懂,我是废物吗
17 回复 分享
发布于 2022-01-25 15:45
这个解法真的豁然开朗,谢谢
17 回复 分享
发布于 2021-12-16 00:26
q2.date = DATE_ADD(q1.date, interval 1 day)这句写得真妙啊
16 回复 分享
发布于 2022-02-10 12:32
妙啊
9 回复 分享
发布于 2021-12-01 20:30
两个表可以分开,我对ON后面的判断语句有点不太理解,因为在我的理解当中,ON后面是用来确定主键的,用下面的方式我觉得比较好理解。 SELECT q1.device_id, q1.date, q2.device_id, q2.date FROM (SELECT DISTINCT device_id, date FROM question_practice_detail)as q1 LEFT JOIN (SELECT DISTINCT device_id, DATE_ADD(question_practice_detail.date, interval 1 day) AS date FROM question_practice_detail)AS q2 ON q1.device_id = q2.device_id AND q1.date = q2.date
8 回复 分享
发布于 2021-12-20 11:41
大佬你好,请问为什么第7行这里用AND而不是where子句呢?
5 回复 分享
发布于 2021-11-21 19:39
看懂了 。。。让我写还是想不出来
2 回复 分享
发布于 2022-05-30 21:05
好牛
1 回复 分享
发布于 2024-04-07 16:52 天津
复制你写的代码不对,我把count(q2.device_id)换成了count(q2.date)就对了
1 回复 分享
发布于 2022-11-19 16:32 上海
题目平均次日留存率,我的理解,不应该是把每一天的次日留存率求出来,然后再求一个平均值吗?with m as ( select t1.date, count(distinct t2.device_id)/count(distinct t1.device_id) rr1 from question_practice_detail t1 left join question_practice_detail t2 on t1.device_id = t2.device_id and t2.date = t1.date + interval "1" day group by t1.date ) select avg(rr1) from m
1 回复 分享
发布于 2022-09-08 11:19 上海
count(q2.device_id)/ count(q1.device_id) 这里两个表不是一样的吗?为什么计算的数不一样啊,连接把我搞懵圈了,count是计算的连接后的列嘛?
1 回复 分享
发布于 2022-09-01 12:20 湖南
大佬,第四行和第六行代码里,为什么把date 放在distinct前面就会报错呢?
1 回复 分享
发布于 2022-07-06 11:37
这个解法确实更容易理解哈
1 回复 分享
发布于 2022-02-24 13:55
太厉害了
点赞 回复 分享
发布于 03-22 21:01 山东
为什么我最后一个连接条件用q1.date = DATE_SUB(q2.date, INTERVAL 1 DAY), 就会和答案里的q2.date = DATE_ADD(q1.date, INTERVAL 1 DAY)得到不一样的比率,同样是做了1天的INTERVAL,大佬是否可以讲解其中的机制。
点赞 回复 分享
发布于 03-10 06:43 上海
大哥大哥,nice
点赞 回复 分享
发布于 2024-05-11 09:55 江苏
大佬,最清晰的解法👍
点赞 回复 分享
发布于 2024-02-26 17:07 上海
不太理解为什么两个相同的表进行外连接会出现空值呢qwq连接的条件字段不是都有值可以对应吗?
点赞 回复 分享
发布于 2023-11-10 09:52 日本
你们复制代码后 答案是正确的吗
点赞 回复 分享
发布于 2023-09-27 11:38 天津

相关推荐

03-31 18:02
门头沟学院 Java
白日梦想家_等打包版:不要的哦佛给我
点赞 评论 收藏
分享
评论
1334
194
分享

创作者周榜

更多
牛客网
牛客企业服务