【问题标题】:Get active users by month按月获取活跃用户
【发布时间】:2021-02-21 19:02:35
【问题描述】:

使用 MySQL,我试图获取我在任何给定月份的活跃用户数。我有一个包含ActivationDateTerminationDate 列的表,如果计算的月份在ActivationDateTerminationDate 之后为空,则用户处于活动状态并且应该被计算在内。我想按月总结这些金额。我想我可以只sum 每边计算总数,但分解它不会给我一个运行总数。我尝试过使用窗口函数,但我没有足够的经验来确切地知道我做错了什么,而且我不确定如何提出正确的问题。

例如,如果我有以下数据...

UserId  ActivationDate  TerminationDate
1  2020-01-01  null
2  2020-01-15  null
3  2020-01-20  2020-01-30
4  2020-02-01  null
5  2020-02-14  2020-02-27
6  2020-02-15  2020-02-28
7  2020-03-02  null
8  2020-03-05  null
9  2020-03-20  2020-03-21

我希望我的结果类似于:

2020-01  2  (there are 2 active users, since one signed up but cancelled before the end of the month)
2020-02  3  (2 from the previous month, plus 1 that signed up this month and is still active)
2020-03  5  (3 from previous, 2 new, 1 cancellation)

【问题讨论】:

    标签: mysql sql datetime count window-functions


    【解决方案1】:

    您可以取消透视,然后汇总和求和。在 MySQL 8.0.14 或更高版本中,您可以使用横向连接:

    select date_format(x.dt, '%Y-%m-01') as dt_month, 
        sum(sum(cnt)) over(order by date_format(x.dt, '%Y-%m-01')) as cnt_active_users
    from mytable t
    cross join lateral (
        select t.activationdate as dt, 1 as cnt
        union all select t.terminationdate, -1
    ) x
    where x.dt is not null
    group by dt_month
    order by dt_month
    

    在早期的 8.x 版本中:

    select date_format(x.dt, '%Y-%m-01') as dt_month, 
        sum(sum(cnt)) over(order by date_format(x.dt, '%Y-%m-01')) as cnt_active_users
    from (
        select activationdate as dt, 1 as cnt from from mytable
        union all select terminationdate, -1 from mytable 
    ) x
    where x.dt is not null
    group by dt_month
    order by dt_month
    

    【讨论】:

    • 不错的一个!感谢那。我会尝试并由我的团队运行它。如果这是我们的答案,我一定会将其标记为已解决。
    【解决方案2】:

    你没有说什么版本的 MySQL。如果您使用的是 8.0,这应该可以工作:

    create table userdates (
        UserId int not null,
        ActivationDate date not null,
        TerminationDate date null
    );
    
    insert into userdates (UserId, ActivationDate, TerminationDate)
    values
      (1, cast("2020-01-01" as date), null      )
    , (2, cast("2020-01-15" as date), null      )
    , (3, cast("2020-01-20" as date), cast("2020-01-30" as date))
    , (4, cast("2020-02-01" as date), null      )
    , (5, cast("2020-02-14" as date), cast("2020-02-27" as date))
    , (6, cast("2020-02-15" as date), cast("2020-02-28" as date))
    , (7,  cast("2020-03-02" as date), null     )
    , (8,  cast("2020-03-05" as date), null     )
    , (9,  cast("2020-03-20" as date), cast("2020-03-21" as date))
    , (10, cast("2020-07-20" as date), null)
    , (11, cast("2019-09-12" as date), cast("2019-09-14" as date));
    
    WITH RECURSIVE d (dt) 
    AS (
          SELECT cast("2019-01-01" as date)
          UNION ALL
          SELECT date_add(dt, interval 1 month)
          FROM d 
          WHERE dt < cast("2020-12-01" as date)
        )
    
    select d.dt
    , count(distinct ud.UserId) as UserCount
    from userdates ud
      right outer join d on d.dt >= date_format(ud.ActivationDate, '%Y-%m-01')
                  and (d.dt <= ud.TerminationDate or ud.TerminationDate is null)
    group by d.dt;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 2017-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-01
      相关资源
      最近更新 更多