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

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

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

思路一: 找出用户连续两天的刷题情况,比如用户1在2021-08-14和2021-08-15都刷题了,那就是连续两天刷题,用户2在2021-08-14刷题了,但2021-08-15没刷题,那就是没有连续两天刷题。

做法:

  • 将第一天和第二天的表连接(由于看的是连续刷题的比例,所以没有连续两天刷题的记录也要保留,用left join);
  • 要实现两张表日期差一天,可以用datediff、date_add、date_sub
select
  distinct a.device_id,
  a.date as date1,
  b.date as date2
from
  question_practice_detail a
  left join question_practice_detail b 
  on a.device_id = b.device_id
  and datediff(b.date, a.date) = 1
-- date_add(a.date, interval 1 day) = b.date
-- date_sub(b.date, interval 1 day) = a.date

得到的结果为: alt

接下来就很简单了,date1列是第一天刷题的情况,date2是第二天刷题的情况,两列求比值就是连续两天刷题的平均概率。

select
  round(count(date2) / count(date1), 4) as avg_ret 
from
  (
    select
      distinct a.device_id,
      a.date as date1,
      b.date as date2
    from
      question_practice_detail a
      left join question_practice_detail b 
      on a.device_id = b.device_id
      and date_add(a.date, interval 1 day) = b.date
  ) c

注意:对date计数不用去重,否则得到的就是天数而不是人数了。

思路二: 直接用窗口函数将用户前后两天的刷题情况拼接起来 注意:这里拼出来的不一定是连续两天,例如用户2在2021-08-11和2021-08-14刷题,中间没有其他记录,窗口函数也会将这两条记录拼起来!所以count里面要区分下情况~

select
  round(
    count(if(datediff(date2, date1) = 1, date2, null)) / count(date1),
    4
  ) as avg_ret
from
  (
    select
      distinct device_id,
      date as date1,
      lead(date, 1) over(
        partition by device_id
        order by
          date asc
      ) as date2
    from
      (
        select
          distinct device_id,
          date
        from
          question_practice_detail
      ) a
  ) b
全部评论
这个有例子,最好理解
点赞 回复 分享
发布于 2022-10-13 12:12 江苏

相关推荐

点赞 评论 收藏
分享
三年之期已到我的offer快到碗里来:9硕都比不上9本
点赞 评论 收藏
分享
4 5 评论
分享
牛客网
牛客企业服务