Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > SQL计算用户平均次日留存率

SQL题目分析之计算用户的平均次日留存率

作者:努力学代码的小two

留存率是指在特定时间段内,仍然继续使用某项产品或服务的用户占用户总数的百分比,这篇文章主要介绍了SQL题目分析之计算用户的平均次日留存率的相关资料,需要的朋友可以参考下

描述

题目:现在运营想要查看用户在某天刷题后第二天还会再来刷题的留存率。请你取出相应数据。

示例:question_practice_detail

iddevice_idquestion_idresultdate
12138111wrong2021-05-03
23214112wrong2021-05-09
33214113wrong2021-06-15
46543111right2021-08-13
52315115right2021-08-13
62315116right2021-08-14
72315117wrong2021-08-15
83214112wrong2021-05-09
93214113wrong2021-08-15
106543111right2021-08-13
112315115right2021-08-13
122315116right2021-08-14
132315117wrong2021-08-15
143214112wrong2021-08-16
153214113wrong2021-08-18
166543111right2021-08-13

根据示例,你的查询应返回以下结果:

avg_ret
0.3000

题目分析

需求:计算用户在某天刷题后,第二天还会再来刷题的留存率

什么是次日留存率?次日留存率 = (第一天刷题的用户中,第二天也来刷题的用户数) / (第一天刷题的总用户数)

示例解读:根据示例数据,最终的平均留存率是 0.3000,即 30%。这意味着,在所有某天刷过题的用户中,平均有 30% 的用户会在第二天继续刷题。

关键点

  1. 用户标识:我们通过 device_id 来唯一标识一个用户。
  2. 行为日期:我们关心的是用户刷题的日期 (date)。
  3. 去重:一个用户在同一天可能刷了多道题,但我们只关心他 “是否来过”,所以需要对 (device_id, date) 进行去重。
  4. 关联:我们需要将用户第一天的行为和第二天的行为关联起来,以判断他是否留存。

解题思路

要计算留存率,我们需要明确两个集合:A. 某日活跃用户集合:在某天 date1 刷过题的用户。B. 次日留存用户集合:在集合 A 中的用户,并且在 date1 的第二天(date1 + 1天)也刷过题。

留存率就是 |B| / |A|

直接计算比较复杂,我们可以换个角度,为每一条 “某日刷题记录” 匹配一条 “次日刷题记录”,然后通过计数来求比率。

  1. 构建用户每日刷题的唯一记录:首先,我们需要一个只包含 (device_id, date) 唯一组合的数据集。
  2. 自连接匹配次日记录:将这个唯一记录数据集与自身进行左连接(LEFT JOIN)。连接条件是:
    • A.device_id = B.device_id (同一个用户)
    • B.date = A.date + INTERVAL 1 DAY (B 表的日期是 A 表日期的第二天)
  3. 计算留存率
    • 左连接的好处是,如果一个用户在第二天没有来,B.date 字段会是 NULL
    • 因此,COUNT(B.date) 就等于 “第二天也来的用户数”。
    • COUNT(A.date) 就等于 “第一天来的总用户数”。
    • 两者相除,就得到了我们想要的平均次日留存率。

分步解析最终代码

-- 外层查询:计算平均次日留存率
select count(date2)/count(date1) as avg_ret
from(
    -- 子查询 A: 为每个用户的每日刷题记录匹配次日是否也刷题
    select distinct 
        qpd.device_id,
        qpd.date as date1,  -- 用户当天刷题的日期
        uniq_id_date.date as date2  -- 用户次日是否刷题的日期(可能为NULL)
    from 
        question_practice_detail as qpd
    left join(
        -- 子查询 B: 获取所有用户所有刷题日期的唯一记录
        select distinct device_id, date
        from question_practice_detail
    )as uniq_id_date
    -- 左连接条件
    on qpd.device_id = uniq_id_date.device_id  -- 同一个用户
    and date_add(qpd.date, interval 1 day) = uniq_id_date.date -- 次日
)as id_last_next_code;

1. 子查询 B (uniq_id_date)

select distinct device_id, date
from question_practice_detail

2. 子查询 A (id_last_next_code)

select distinct 
    qpd.device_id,
    qpd.date as date1,
    uniq_id_date.date as date2
from 
    question_practice_detail as qpd
left join
    uniq_id_date
on 
    qpd.device_id = uniq_id_date.device_id
    and date_add(qpd.date, interval 1 day) = uniq_id_date.date

3. 外层查询

select count(date2)/count(date1) as avg_ret
from id_last_next_code;

总结

这道题的解法非常巧妙地运用了“自连接”“左连接”的技巧。

  1. 自连接:通过将一个去重后的 “用户 - 日期” 表与自身连接,我们能够在一条记录里同时看到一个用户在两天的行为。
  2. 左连接:通过左连接,我们确保了不会丢失任何一个 “第一天” 的用户行为记录,同时用 NULL 值清晰地标记出了哪些用户没有在 “第二天” 回来。
  3. 计数与除法:最后,利用 COUNT() 函数对非空值的计数特性,轻松地计算出了分子(留存数)和分母(总活跃数),从而得到了最终的留存率。

这种模式在用户行为分析中非常常见,例如计算 7 日留存、月留存等,核心思想都是类似的。

到此这篇关于SQL题目分析之计算用户的平均次日留存率的文章就介绍到这了,更多相关SQL计算用户平均次日留存率内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文