【解法一】
思路
①按用户去重查每天答题记录
②加个子查询查该用户当天+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