代码之家  ›  专栏  ›  技术社区  ›  Raphael

使用SQL查询多天的保留率

  •  0
  • Raphael  · 技术社区  · 5 年前

    给出了一个由 user 桌子和桌子 check_in 有一张桌子 date 字段,我想计算用户的保留日期。例如,对于所有有一个或多个签入的用户,我想要在第二天和第三天签入的用户百分比,以此类推。

    我的SQL技能非常基础,因为它不是我日常工作中经常使用的工具,我知道这超出了我习惯的查询类型。我一直在研究数据透视表来实现这一点,但我不确定这是否是正确的路径。

    编辑:

    用户表没有注册日期。可以假设它只包含本例中的ID。

    下面是一些关于 登记 表:

    |   user_id   |         date        |
    =====================================
    | 1           | 2020-09-02 13:00:00 |   
    -------------------------------------
    | 4           | 2020-09-04 12:00:00 |
    -------------------------------------
    | 1           | 2020-09-04 13:00:00 |
    -------------------------------------
    | 4           | 2020-09-04 11:00:00 |
    -------------------------------------
    |                ...                |
    -------------------------------------
    

    查询的预期输出如下:

    | day_0 | day_1 | day_2 | day_3 |
    =================================
    | 70%   | 67 %  | 44%   | 32%   |
    ---------------------------------
    

    请注意,我在这个输出中使用了随机数,只是为了说明格式。

    0 回复  |  直到 5 年前
        1
  •  1
  •   Gordon Linoff    5 年前

    哦,我明白了。假设您的意思是用户的签入间隔天数——而用户可能没有签入时间——那么只需使用聚合和窗口功能:

    select sum( (ci.date = ci.min_date)::numeric ) / u.num_users as day_0,
           sum( (ci.date = ci.min_date + interval '1 day')::numeric ) / u.num_users as day_1,
           sum( (ci.date = ci.min_date + interval '2 day')::numeric ) / u.num_users as day_2
    from (select u.*, count(*) over () as num_users
          from users u
         ) u left join
         (select ci.user_id, ci.date::date as date,
                 min(min(date::date)) over (partition by user_id order by date) as min_date
          from checkins ci
          group by user_id, ci.date::date
         ) ci;
    

    请注意,这会聚合 checkins 按用户id和日期列出的表。这样可以确保每个日期只有一行。