sql常见笔试题目类型(4)n日留存率

sql最常考察的一部分内容都是和时间函数有关的,这其实与常用的分析指标都与时间相关有关。这里主要就说一下留存率的计算思路与方法。
首先要从留存率的概念进行入手,留存率=活跃的用户÷新用户,以计算每天的n日留存率为例,想要算n日留存率,其实就是要每天新用户的数量以及第n天活跃用户的数量。
所以留存率的计算可以分成两步,第一步是找到每天的新用户并计算数量,日期格式是可以直接比较大小的,所以每个用户登录日期最小的时间就是新用户的登录日期;
第二步,计算新用户在n天后登录情况,这个有很多种统计方式,这里用左链接的方法来实现,在第一步选出日期之后,按照时间一个左链接,左链接的条件可以直接设置为日期相差为n天(如on a.id=b.id and a.date=b.data+n),然后就是对当天的用户数和n天后登录的用户数进行统计并做比。

拿牛客网上一个略有出入的简化题目作为示例,这道题主要是突出了第二步的使用。

牛客网SQL29 计算用户的平均次日留存率
https://www.nowcoder.com/practice/126083961ae0415fbde061d7ebbde453

题目:现在运营想要查看用户在某天刷题后第二天还会再来刷题的平均概率。请你取出相应数据。
sql常见笔试题目类型(4)n日留存率_第1张图片
根据示例,你的查询应返回以下结果:
sql常见笔试题目类型(4)n日留存率_第2张图片
这里没有限制日期,所以求得是所有用户的平均次日留存率,由于会存在同一用户在一天重复登录的情况,所以要对用户进行去重,这里要注意在引用表的时候首先进行去重,而不是在统计数量的时候去重,其他就是照着上面第二步,对数据进行一次左链接并计数。还有一点就是date数据的数量关系,如果更专业一点应该用日期函数date_sub、datediff进行加减。

select count(q2.device_id)/count(q1.device_id)
from (select distinct device_id,date from question_practice_detail) q1
left join (select distinct device_id,date from question_practice_detail) q2 
on q1.device_id=q2.device_id and q2.date=q1.date+1

又找了一个完整的次日留存率示例

每个日期新用户的次日留存率

牛客每天有很多人登录,请你统计一下牛客每个日期新用户的次日留存率。
有一个登录(login)记录表,简况如下:
sql常见笔试题目类型(4)n日留存率_第3张图片
请你写出一个sql语句查询每个日期新用户的次日留存率,结果保留小数点后面3位数(3位之后的四舍五入),并且查询结果按照日期升序排序,上面的例子查询结果如下:
sql常见笔试题目类型(4)n日留存率_第4张图片
这里就是用的上面的那个思路,只是要注意的是,这里要求的是不管是否有新用户,每天的数据都要列出来,所以在计算出表中有数据的日期外,还要添加没有出现的日期的次日留存率,用union进行合并。这一种方法比较直观,同样还有一种通过case when来做的,思想是相同的,只是利用case when把统计的过程放在了一起。

select a.date,round(count(distinct login.user_id)/ count(a.user_id),3) as p
from (select user_id, min(date) as date from login group by user_id) as a
left join login
on login.user_id=a.user_id and login.date=DATE_ADD(a.date,INTERVAL 1 DAY)
group by a.date
union
select date,0.000 as p
from login
where date not in(select min(date) from login group by user_id)
order by date;

写SQL感觉就是在做指标拆解,对于不能直接获取的需求,都考虑通过其数学表达式进行拆分,如果仍不能直接获取就继续拆分,直到所有的需求都能用数据库的数据直接表达出来,然后对这些表达式进行组合优化,得到sql的最优解。

你可能感兴趣的:(SQL,算法刷题,sql,数据库)