postgresql - 统计每月的时事通讯订阅者总数

标签 postgresql amazon-redshift

现在,我绞尽脑汁想了几个小时,想弄清楚如何使用 Redshift 计算每个月的时事通讯订阅者总数

计算的基础是一个事件表,该表跟踪每个用户操作,特别是他是订阅还是取消订阅时事通讯。简化后看起来像这样:

+----------------------+---------+---------------+
| timestamp            | user_id | action        |
+----------------------+---------+---------------+
| 2017-01-01T12:10:31Z |       1 | subscribed    |
| 2017-01-01T13:11:51Z |       2 | subscribed    |
| 2017-01-01T13:15:53Z |       3 | subscribed    |
| ...                  | ...     | ...           |
| 2017-02-17T09:42:33Z |       4 | subscribed    |
| ...                  | ...     | ...           |
| 2017-03-15T16:59:13Z |       1 | unsubscribed  |
| 2017-03-17T02:19:56Z |       2 | unsubscribed  |
| 2017-03-17T05:33:05Z |       2 | subscribed    |
| ...                  | ...     | ...           |

对于每个月,我都想总结订阅 时事通讯的用户数量加上已经订阅 但没有退订的用户数量。在上面的示例中,我们在 1 月份有 3 个用户,在 2 月份添加了另一个用户,总共有 4 个订阅者。然后在 3 月,我们失去了一个用户,而另一个用户只是暂时取消订阅。我们 3 月份的订阅者总数为 3。

我正在寻找的最终结果是这样的:

+------------+-------------+
| month      | subscribers |
+------------+-------------+
| 2017-01-01 |           3 |
| 2017-02-01 |           4 |
| 2017-03-01 |           3 |
| ...        |         ... |

是否以及如何使用 SQL 查询解决这个问题(最好在 Redshift 或 Postgres 中工作)有什么想法吗?

最佳答案

解决方法是:

1) 创建一个存储日期的日历表(表中的一行是唯一的日期),请参阅 this 中的更多信息问题。这对于大多数 BI 查询来说非常方便。

2) 编写包含以下步骤的查询:

2a) 基于订阅/取消订阅事件,为每个用户构建订阅状态的时间范围(首先使用 lead 函数为每个给定的事件识别下一个事件并选择必要的对)。如果用户只有一个订阅事件,请使用 coalescedate_to 设置为当前日期。

2b) 将这些范围加入到日历表中,这样一行就是一个日期/用户

2c) 使用一种或另一种方法计算行数(唯一 ID、平均每日、每月的第一天、每月的最后一天)

查询看起来像这样:

with
next_events as (
    select
     user_id
    ,"timestamp"::date as date_from
    ,action
    ,lead(timestamp) over (partition by user_id order by timestamp) ::date as date_to
    ,lead(action) over (partition by user_id order by timestamp) as next_action
    from your_table
    where action in ('subscribed','unsubscribed')
)
,ranges as (
    select 
     user_id
    ,date_from
    ,coalesce(date_to,current_date) as date_to
    from next_events
    where (action='subscribed' and next_action='unsubscribed')
    or (action='subscribed' and next_action is null)
)
,subscriber_days as (
    select 
     t1.user_id
    ,t2.date
    from ranges t1
    join calendar t2
    on t2.date between t1.date_from and t1.date_to
)
-- use whatever method needed to identify monthly N from daily N (first day, last day, average, etc.)
-- below is the unique count
select
 date_trunc('month',date) as date
,count(distinct user_id) as subscribers
from subscriber_days
group by 1
order by 1

关于postgresql - 统计每月的时事通讯订阅者总数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48122500/

相关文章:

postgresql - PostgreSQL 穷尽一个序列时的错误类型是什么?

sql - 如何在 PostgreSQL 9 中用 GROUP BY 替换 DISTINCT ON?

postgresql - Redshift COPY 语句加载日期格式,带两位数年份 (mm/dd/yy)

postgresql - 使用不正确的日期值将 csv 导入 Postgres 数据库

sql - 在 redshift 中使用正则表达式

sql - postgresql - 选择 4 列,其中 1 列需要过滤

ruby-on-rails - 在 Rails + Postgres 中仅附加 jsonb 列

sql - 使用日期选择交易

postgresql - 将数据保留在运行 Postgres DB 的 Azure 容器应用程序中

amazon-web-services - 在 Redshift 中插入