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

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

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),一直不知道怎么处理这种信息,学习了
28 回复 分享
发布于 2022-02-27 16:16
这个解法真的豁然开朗,谢谢
16 回复 分享
发布于 2021-12-16 00:26
我咋看不懂,我是废物吗
16 回复 分享
发布于 2022-01-25 15:45
q2.date = DATE_ADD(q1.date, interval 1 day)这句写得真妙啊
14 回复 分享
发布于 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
7 回复 分享
发布于 2021-12-20 11:41
大佬你好,请问为什么第7行这里用AND而不是where子句呢?
5 回复 分享
发布于 2021-11-21 19:39
看懂了 。。。让我写还是想不出来
2 回复 分享
发布于 2022-05-30 21:05
这个解法确实更容易理解哈
1 回复 分享
发布于 2022-02-24 13:55
大佬,第四行和第六行代码里,为什么把date 放在distinct前面就会报错呢?
1 回复 分享
发布于 2022-07-06 11:37
count(q2.device_id)/ count(q1.device_id) 这里两个表不是一样的吗?为什么计算的数不一样啊,连接把我搞懵圈了,count是计算的连接后的列嘛?
1 回复 分享
发布于 2022-09-01 12:20 湖南
题目平均次日留存率,我的理解,不应该是把每一天的次日留存率求出来,然后再求一个平均值吗?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(q2.date)就对了
1 回复 分享
发布于 2022-11-19 16:32 上海
好牛
1 回复 分享
发布于 04-07 16:52 天津
请问count括号中是不能嵌套select语句或使用 distinct的是吗
点赞 回复 分享
发布于 2021-12-12 18:57
太牛啦
点赞 回复 分享
发布于 2022-02-22 20:45
目前看到最简洁方式,学习了,大佬!感谢!
点赞 回复 分享
发布于 2022-02-25 16:08
请问一下不用左外连接,用inner join on 可以吗?
点赞 回复 分享
发布于 2022-02-26 16:35
(SELECT DISTINCT device_id, date FROM question_practice_detail)as q1 (SELECT DISTINCT device_id, date FROM question_practice_detail) AS q2 这两个表的内容不是一样的吗?
点赞 回复 分享
发布于 2022-03-02 23:21
使用DISTINCT 对device_id第一次去重时,怎么保证留下的是哪个日期的信息呢?第二次去重计算日期不是以第一次的日期结果为基准进行判定的吗
点赞 回复 分享
发布于 2022-04-17 14:21

相关推荐

Noob1024:一笔传三代,人走笔还在
点赞 评论 收藏
分享
我是小红是我:学校换成中南
点赞 评论 收藏
分享
1199 185 评论
分享
牛客网
牛客企业服务