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 outer join (select distinct device_id,date from question_practice_detail) as q2 on q1.device_id=q2.device_id AND q1.date=DATE_SUB(q2.date,INTERVAL 1 DAY)
现在运营想要查看用户在某天刷题后第二天还会再来刷题的留存率。请你取出相应数据。
转载
所谓次日留存,指的是同一用户(在本题中则为同一设备,即device_id)在当天和第二天都进行刷题。注意,在这题我们不关心同一用户(设备)在这天答了什么题、答题结果如何,只关心他是否答题,因此对于这题来说存在重复的数据(如下图红框所示),需要使用 DISTINCT
去重。
而次日留存率可以这样表示:
次日留存率=去重的数据表中符合次日留存的条目数目去重的数据表中所有条目数目次日留存率=去重的数据表中所有条目数目去重的数据表中符合次日留存的条目数目
具体而言,使用两个子查询,查询出两个去重的数据表,并使用条件(q2.date应该是q1.date的后一天)进行筛选,如下所示(数据未显示完全,从左至右顺序,列表名为 q1.device_id, q1.date, q2.device_id, q2.date)
因为使用的是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的条目