【解法一】
思路
①按用户去重查每天答题记录
②加个子查询查该用户当天+1天是否有答题记录,有则赋值1 as date2
③把②中的date加起来除以①中的用户数,得到次日留存率
知识点
第二天计算
date=adddate(date,interval 1 day)
SQL代码
select sum(date2)/count(device_id) as avg_ret from ( select distinct device_id, date, (select 1 as aa from question_practice_detail q2 where q2.date=adddate(q1.date,interval 1 day) and q2.device_id=q1.device_id group by device_id,date ) date2 from question_practice_detail q1 )t
【解法二】(记录大佬思路)
思路
①练习作答记录表自关联,关联条件两张表的日期间隔datediff(q1.date,q2.date)=1,如果不为空说明第二天有答题记录
②再计算两张表按日期对用户进行去重计数,相除后得到平均次日留存
知识点
datediff(),计算日期间隔
代码
select count(distinct q2.device_id,q2.date)/count(distinct q1.device_id,q1.date) as avg_cnt from question_practice_detail q1 left join question_practice_detail q2 on q1.device_id=q2.device_id and datediff(q2.date,q1.date)=1
【解法三】(记录大佬思路)
思路
①用排序窗口函数lead()over() 算出当前日期前一次答题日期,按用户分组,按日期排序
②计算当前日期和前一次答题日期的时间差,如果时间差等于1,说明有答题,赋值1,否则赋值0
③求均值,即为次日留存
知识点
lead(字段名)over([partiton by ] order by )当前字段的前1条数据的值
代码
select avg(if(datediff(next_date, date) = 1, 1, 0)) as avg_ret from ( select distinct device_id, date, lead(date) over ( partition by device_id order by date ) as next_date from ( select distinct device_id, date from question_practice_detail ) t1 ) t2