现在,我绞尽脑汁想了几个小时,想弄清楚如何使用 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
函数为每个给定的事件识别下一个事件并选择必要的对)。如果用户只有一个订阅事件,请使用 coalesce
将 date_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/