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

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

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

WITH t1 AS (
    SELECT uid,
           in_time
    FROM tb_user_log
    UNION ALL
    SELECT uid,
           out_time AS in_time
    FROM tb_user_log
),
t2 AS (
    SELECT uid,
           in_time,
           RANK() over (PARTITION BY uid ORDER BY uid ASC, in_time ASC ) AS num_1
    FROM t1
),
t3 AS (
    # 获取最大时间
    SELECT
           max(DATE(in_time)) AS max_date
    FROM t2
),
t4 AS (
    # 获取时间节点,7d,30d前
    SELECT max_date,
           DATE_ADD(max_date, INTERVAL -6 DAY ) AS last_7d,
           DATE_ADD(max_date, INTERVAL -29 DAY ) AS last_30d
    FROM t3
),
t5 AS (
    SELECT *
    FROM t2
    JOIN t4
),
t6 AS (
    # 近七日新晋用户情况
    SELECT uid
    FROM t5
    WHERE num_1 = 1 AND DATE (in_time) BETWEEN last_7d AND max_date
    GROUP BY uid
),
t7 AS (
    # 近7天活跃过且非新晋用户
    SELECT uid
    FROM t5
    WHERE DATE (in_time) BETWEEN last_7d AND max_date
    AND uid not in (SELECT uid FROM t6)
    GROUP BY uid
),
t8 AS (
    # 30d内活跃的用户
    SELECT uid
    FROM t5
    WHERE DATE(in_time) BETWEEN last_30d AND max_date
    GROUP BY uid
),
t9 AS (
    # 30d前活跃的用户
    SELECT uid
    FROM t5
    WHERE DATE(in_time) < last_30d
),
t10 AS (
    # 流失用户
    SELECT uid
    FROM t9
    WHERE uid NOT IN (SELECT uid FROM t8)
    GROUP BY uid
),
t11 AS (
    # 7d内活跃的用户
    SELECT uid
    FROM t5
    WHERE DATE(in_time) BETWEEN last_7d AND max_date
    GROUP BY uid
),
t12 AS (
    # 7d前活跃的用户
    SELECT uid
    FROM t5
    WHERE DATE(in_time) < last_7d
),
t13 AS (
    # 流失用户
    SELECT uid
    FROM t12
    WHERE uid NOT IN (SELECT uid FROM t11) AND uid NOT IN (SELECT uid FROM t10)
    GROUP BY uid
),
t14 AS (
    SELECT '忠实用户'     AS user_grade,
           count(uid) AS user_num
    FROM t7
    UNION ALL
    SELECT '新晋用户'     AS user_grade,
           count(uid) AS user_num
    FROM t6
    UNION ALL
    SELECT '沉睡用户'     AS user_grade,
           count(uid) AS user_num
    FROM t10
    UNION ALL
    SELECT '流失用户'     AS user_grade,
           count(uid) AS user_num
    FROM t13
),
t15 AS (
    SELECT SUM(user_num) AS sum_num
    FROM t14
),
t16 AS (
    SELECT t14.user_grade,
           ROUND(t14.user_num / t15.sum_num,2) AS ratio
           FROM t14
    JOIN t15
)
SELECT * FROM t16;

# 这道题的关键在于如何基于规则进行构建,而且关键时间节点很重要,可以提前计算!

全部评论

相关推荐

06-20 17:42
东华大学 Java
凉风落木楚山秋:要是在2015,你这简历还可以月入十万,可惜现在是2025,已经跟不上版本了
我的简历长这样
点赞 评论 收藏
分享
点赞 评论 收藏
分享
07-03 16:02
门头沟学院 Java
今天面试,非常紧张,面试官问我springboot有哪些核心模块都答不上来了,真的对自己无语了!
程序员小白条:28届我勒个去,很多人面试都没机会
查看1道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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