SQL 70) 查询每个日期新用户的次日留存率

牛客每个人最近的登录日期(五)

http://www.nowcoder.com/questionTerminal/ea0c56cd700344b590182aad03cc61b8

发现其他大神的一个很好懂的解法!

  • 求出新用户第一天登录日期
    SELECT user_id,MIN(date) AS date FROM login GROUP BY user_id
  • 算出有新用户登录的日期的新用户留存率
    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 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;

补充其他大神的CASE WHEN 解法

select date
        ,ifnull(round((sum(case when (user_id,date)in
            (select user_id,date_add(date,interval -1 day) 
             from login group by user_id)
            then 1 else 0 end))/
        (sum(case when (user_id,date)in
            (select user_id,min(date)from login group by user_id)
            then 1 else 0 end)),3),0)as p
from login
group by date
order by date;
SQL 文章被收录于专栏

SQL

全部评论
SELECT date, ifnull( round( (sum (case when (user_id, date) in ( select user_id, date_add(date,interval -1 day) from login group by user_id ) and (user_id,date) in (select user_id,min(date)from login group by user_id) then 1 else 0 end) ) / (sum (case when (user_id,date)in (select user_id,min(date)from login group by user_id) then 1 else 0 end) ) ,3) ,0)as p from login group by date order by date
1 回复 分享
发布于 2021-08-08 10:54
算留存用户人数的时候,不会把每天都登录的老用户也算进去吗?
1 回复 分享
发布于 2021-06-14 14:43
select date, ifnull ( round ( ( sum( case when (user_id, date_add(date, interval 1 day)) in ( select user_id, date from login group by user_id ) then 1 else 0 end ) / sum( case when (user_id, date) in ( select user_id, min(date) from login group by user_id ) then 1 else 0 end ) ), 3), 0) p from login group by date_add(date, interval 1 day) order by date; 按照个人理解修改的大神解法,也许会更容易理解一些
2 回复 分享
发布于 2021-02-15 10:10
看不懂这个interval -1 day什么意思
1 回复 分享
发布于 2022-04-11 18:46
select date ,ifnull(round((sum(case when (user_id,date)in (select user_id,date_add(date,interval -1 day) from login group by user_id) then 1 else 0 end))/ (sum(case when (user_id,date)in (select user_id,min(date)from login group by user_id) then 1 else 0 end)),3),0)as p from login group by date order by date; 这个答案我也是这个思路 但会通过4/5,争取后续能出修复
点赞 回复 分享
发布于 02-27 01:46 江苏
with t as (select *,lead(date,1) over(partition by user_id order by date) as n_d ,dense_rank() over(partition by user_id order by date) as rk from login) select date,ifnull(round(count(distinct case when n_d is not null and n_d-date = 1 then user_id end ) / count(case when rk= 1 then user_id end),3) ,0) as p from t group by date order by date
点赞 回复 分享
发布于 2022-01-02 23:29
大佬,这句是什么意思啊,看了半天看不到 case when (user_id,date)in (select user_id,date_add(date,interval -1 day) from login group by user_id
点赞 回复 分享
发布于 2021-12-16 00:38
再第一种方法基础上改了一下: select a.date, round( count(case when date_sub(b.date, interval 1 day) = a.date then a.user_id end) / count(distinct a.user_id),2 ) p from (select user_id,min(date) as date from login group by user_id) AS a join (select user_id,date from login) b on a.user_id = b.user_id group by a.date union select date ,0.00 from login where date not in (select min(date) from login group by user_id) order by date
点赞 回复 分享
发布于 2021-10-16 22:16
很好懂的解法运行不出来
点赞 回复 分享
发布于 2021-10-07 15:19
看半天看不明白第一个sum那里为什么可以这么用 sum(case when (user_id,date)in (select user_id,date_add(date,interval -1 day) from login group by user_id 感觉这里的结果就是0啊
点赞 回复 分享
发布于 2021-10-03 14:38
大佬,为什么要用前一天的除以今天的呢?
点赞 回复 分享
发布于 2021-02-22 16:12

相关推荐

牛油果甜奶昔:别的先不说,牛客还能内推护士?
点赞 评论 收藏
分享
评论
57
9
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务