题解 | #SQL 10.统计活跃间隔对用户分级结果#

统计活跃间隔对用户分级结果

http://www.nowcoder.com/practice/6765b4a4f260455bae513a60b6eed0af

统计活跃间隔对用户分级结果

明确题意:

统计活跃间隔对用户分级后,各活跃等级用户占比,结果保留两位小数,且按占比降序排序


问题分解:

  • 计算每个用户最早最晚活跃日期(作为子表t_uid_first_last):

    • 按用户ID分组:GROUP BY uid
    • 统计最早活跃:MIN(DATE(in_time)) as first_dt
    • 统计最晚活跃:MAX(DATE(out_time)) as last_dt
  • 计算当前日期和总用户数(作为子表t_overall_info):

    • 获取当前日期:MAX(DATE(out_time)) as cur_dt
    • 统计总用户数:COUNT(DISTINCT uid) as user_cnt
  • 左连接两表,即将全表统计信息追加到每一行上:t_uid_first_last LEFT JOIN t_overall_info ON 1

  • 计算最早最晚活跃离当前天数差(作为子表t_user_info):

    • 最早活跃距今天数:TIMESTAMPDIFF(DAY,first_dt,cur_dt) as first_dt_diff
    • 最晚(最近)活跃距今天数:TIMESTAMPDIFF(DAY,last_dt,cur_dt) as last_dt_diff
  • 计算每个用户的活跃等级:

    CASE
        WHEN last_dt_diff >= 30 THEN "流失用户"
        WHEN last_dt_diff >= 7 THEN "沉睡用户"
        WHEN first_dt_diff < 7 THEN "新晋用户"
        ELSE "忠实用户"
    END as user_grade
    
  • 统计每个等级的占比:

    • 按用户等级分组:GROUP BY user_grade

    • 计算占比,总人数从子表得到,非聚合列避免语法错误加了MAX:COUNT(uid) / MAX(user_cnt) as ratio

    • 保留2位小数:ROUND(x, 2)


细节问题:

  • 表头重命名:as
  • 按占比降序排序:ORDER BY ratio DESC;;

完整代码:

SELECT user_grade, ROUND(COUNT(uid) / MAX(user_cnt), 2) as ratio
FROM (
    SELECT uid, user_cnt,
        CASE
            WHEN last_dt_diff >= 30 THEN "流失用户"
            WHEN last_dt_diff >= 7 THEN "沉睡用户"
            WHEN first_dt_diff < 7 THEN "新晋用户"
            ELSE "忠实用户"
        END as user_grade
    FROM (
        SELECT uid, user_cnt,
            TIMESTAMPDIFF(DAY,first_dt,cur_dt) as first_dt_diff, 
            TIMESTAMPDIFF(DAY,last_dt,cur_dt) as last_dt_diff
        FROM (
            SELECT uid, MIN(DATE(in_time)) as first_dt,
                MAX(DATE(out_time)) as last_dt
            FROM tb_user_log
            GROUP BY uid
        ) as t_uid_first_last
        LEFT JOIN (
            SELECT MAX(DATE(out_time)) as cur_dt,
                COUNT(DISTINCT uid) as user_cnt
            FROM tb_user_log
        ) as t_overall_info ON 1
    ) as t_user_info
) as t_user_grade
GROUP BY user_grade
ORDER BY ratio DESC;
SQL大厂真题 文章被收录于专栏

大厂真题手把手教你怎么解~

全部评论
统计最晚活跃:MAX(DATE(out_time)) as last_dt 和获取当前日期:MAX(DATE(out_time)) as cur_dt不都是一样的嘛 用timestampdiff 结果不是1吗 小白求解
点赞 回复 分享
发布于 2021-12-12 22:44
为什么left join后面可以直接on 1?
6 回复 分享
发布于 2021-12-10 15:44
我是废物啊
5 回复 分享
发布于 2022-05-10 12:22
大厂的题难就难在梳理逻辑层次
5 回复 分享
发布于 2022-07-10 17:34
请问round(count(uid)/max(user_cnt)里为什么要除以max(user_cnt)呢?
1 回复 分享
发布于 2022-03-15 14:50
巧秒啊
1 回复 分享
发布于 2022-04-10 16:01
可以只用两层嵌套select case when datediff(m,ma)>29 then '流失用户' when datediff(m,ma)>6 then '沉睡用户' when datediff(m,mi) <7 then '新晋用户' else '忠实用户' end as user_grade, round(count(uid)/max(sm),2) as ratio from( select uid, min(in_time) as mi, max(out_time) as ma, (select max(out_time) from tb_user_log) as m, (select count(distinct uid) from tb_user_log) as sm from tb_user_log group by 1) as t1 group by 1 order by 2 desc
1 回复 分享
发布于 2022-07-20 17:27
我就是个废物啊
1 回复 分享
发布于 2022-12-08 22:52 江苏
大佬
点赞 回复 分享
发布于 2022-05-03 21:29
请问 WHEN first_dt_diff < 7 THEN "新晋用户" 这里为什么不能换成 WHEN last_dt_diff < 7 THEN "新晋用户"
点赞 回复 分享
发布于 2022-05-26 18:51
请问为什么省去一层嵌套之后没法通过呢? SELECT ( CASE WHEN last_dt_diff >= 30 THEN "流失用户" WHEN last_dt_diff >= 7 THEN "沉睡用户" WHEN first_dt_diff < 7 THEN "新晋用户" ELSE "忠实用户" END) as user_grade, round(COUNT(uid) / MAX(user_cnt),2) as ratio FROM ( SELECT uid, user_cnt, TIMESTAMPDIFF(DAY,first_dt,cur_dt) as first_dt_diff, TIMESTAMPDIFF(DAY,last_dt,cur_dt) as last_dt_diff FROM ( SELECT uid, MIN(DATE(in_time)) as first_dt, MAX(DATE(out_time)) as last_dt FROM tb_user_log GROUP BY uid ) as t_uid_first_last LEFT JOIN ( SELECT MAX(DATE(out_time)) as cur_dt, COUNT(DISTINCT uid) as user_cnt FROM tb_user_log ) as t_overall_info ON 1 ) as t_user_info GROUP BY user_grade ORDER BY ratio DESC;
点赞 回复 分享
发布于 2022-05-26 19:04
“非聚合列避免语法错误加了MAX”没明白 请问是为何非聚合列需要加MAX
点赞 回复 分享
发布于 2022-06-20 11:27
子表t_overall_info中user_cnt,统计的是最晚日期登出的去重用户数,这个数是7,但是并不代表忠诚用户、沉睡用户这4类的用户数是7啊,为什么直接除uesr_cnt,还请大佬们赐教
点赞 回复 分享
发布于 2022-07-02 10:49
101用户存在8月和11月各活跃了一次记录,在判断的时候把8月份定义为了流失用户,11月的那次记录定义为了忠实用户
点赞 回复 分享
发布于 2022-08-10 16:08
不会有bug吗,用户最后一次登录时间>=30,肯定也>=7.那么既是流失用户又是沉睡用户
点赞 回复 分享
发布于 2022-08-25 11:03 北京
请问‘左连接两表,即将全表统计信息追加到每一行上:t_uid_first_last LEFT JOIN t_overall_info ON 1’中的on 1 是什么意思啊
点赞 回复 分享
发布于 2023-04-17 17:04 上海
ELSE "忠实用户" 为什么其他的就是忠实用户了呢 case WHEN last_dt_diff >= 30 THEN "流失用户" WHEN last_dt_diff >= 7 THEN "沉睡用户" WHEN first_dt_diff < 7 THEN "新晋用户" ELSE "忠实用户" 忠实用户前三个用户是互斥关系吗不太理解这里
点赞 回复 分享
发布于 2023-04-21 10:14 辽宁
新近用户是最早活跃时间差<7可以理解,忠实用户不应该是最早时间差>7且最晚时间差<7,沉睡用户是最晚时间差>7且<30,流失用户是最晚时间差>30这样理解才对啊,不然的话这些用户都相互包含了
点赞 回复 分享
发布于 2024-06-22 09:08 吉林
近7天范围[T-6, T],时间差是6,我写7会用例不通过,你是怎么过的?
点赞 回复 分享
发布于 01-10 17:45 浙江

相关推荐

01-14 19:01
吉首大学 Java
黑皮白袜臭脚体育生:加个项目吧,一般需要两个项目一业务一轮子呢,简历统一按使用了什么技术实现了什么功能解决了什么问题或提升了什么性能指标来写
点赞 评论 收藏
分享
头像
02-15 16:23
中南大学 Java
野猪不是猪🐗:签了美团真是不一样! 亲戚们都知道我签了美团,过年都围着我问送一单多少钱,还让弟弟妹妹们引以为戒,笑我爸我妈养了个🐢孩子,说从小就知道我这个人以后肯定没出息,我被骂的都快上天了
点赞 评论 收藏
分享
评论
137
10
分享

创作者周榜

更多
牛客网
牛客企业服务