题解 | #2021年11月每天新用户的次日留存率#

2021年11月每天新用户的次日留存率

https://www.nowcoder.com/practice/1fc0e75f07434ef5ba4f1fb2aa83a450

1、题目要求我们统计新用户的留存率,翻译成人话就是,计算用户的第一次登录和第二次登录(跨天)是否相隔一天,不在乎后续的登录操作,因此,我们直接row_number分别取rn为1和2的即可,然后用rn为1的作为主表,关联rn为2的,datediff函数判断结果是否为1即可

2、而何时登录,数据里并未直接告诉我们,但是数据里有intime和outtime,我们只需对这两个时间进行一个简单的列转行即可,但要注意应该用union而非union all,因为如果同一天登入又登出,或者同一天多次登入或登出,我们应将其看做一次登录,而上一题用union all是因为我们求解的维度是文章,而非用户

3、由于我们要对t表数据进行两次应用,因此我们将t表使用with as 作为一个临时表提前查出其结果,之后left join的时候,可能存在一个情况,那就是用户就今天登录一次,之后就再无登录过了,但由于这部分数据我们也要作为分母参与平均,因此不将其过滤,而是如果链接不上为null,就给其一个最大的日期即可,反正相减结果不为1

4、题目里限制要求,只要11月份的新用户数据,因此我们对t1进行相应的月份过滤即可,这个过滤千万不要写在union的两个子句中,因为写在那里,会直接将10月的新用户,又在11月登录的数据,看成第一次登录,这显然是不合理的,我们直接在最外层过滤即可,反正我将全部数据都给你,最后你只要11月的,我给你过滤就好了

with t as (
    select
    uid,
    dt,
    row_number() over(partition by uid order by dt) as rn
    from
    (
        select
        uid,
        date(in_time) as dt
        from tb_user_log
        union
        select
        uid,
        date(out_time) as dt
        from tb_user_log
    )a
)
select
t1.dt as dt,
round(
    avg(if(datediff(ifnull(t2.dt,'9999-12-31'),t1.dt) = 1, 1, 0)),2
) as uv_left_rate
from t as t1
left join t as t2
on t1.uid = t2.uid and t2.rn = 2
where t1.rn = 1 and date_format(t1.dt,'%Y-%m') = '2021-11'
group by dt
order by dt

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-07 12:04
毕业生招你惹你了,问一个发薪日来一句别看网上乱七八糟的你看哪个工作没有固定发薪日扭头就取消了面试就问了一句公司都是这个态度吗还搞上人身攻击了...
程序员小白条:呃呃呃,都还没面试,我都不会问这么细,何况通不通过,去不去都另说,你没实力和学历的话,在外面就这样,说实话没直接已读不回就不错了,浪费时间基本上
点赞 评论 收藏
分享
酷酷我灵儿帅:这去不去和线不线下面说实话没啥关系
点赞 评论 收藏
分享
一表renzha:手写数字识别就是一个作业而已
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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