【问题标题】:Calculate Churn by aggregating by date range in SQL通过在 SQL 中按日期范围聚合来计算流失率
【发布时间】:2020-05-26 01:00:06
【问题描述】:

我正在尝试从包含 customer_id、group、date 的数据中计算流失率。聚合将按 id、组和日期进行。流失公式为(customers in previous cohort - customers in last cohort)/customers in previous cohort

先前同类群组中的客户是指 28 天之前的同类群组 上一个群组中的客户是指过去 28 天的群组

我不确定如何按日期范围汇总它们以计算流失率。

这是我从SQL Group by Date Range复制的示例数据:

Date        Group    Customer_id
2014-03-01  A         1
2014-04-02  A         2
2014-04-03  A         3
2014-05-04  A         3
2014-05-05  A         6
2015-08-06  A         1
2015-08-07  A         2
2014-08-29  XXXX      2
2014-08-09  XXXX      3
2014-08-10  BB        4
2014-08-11  CCC       3
2015-08-12  CCC       2
2015-03-13  CCC       3
2014-04-14  CCC       5
2014-04-19  CCC       4
2014-08-16  CCC       5
2014-08-17  CCC       3
2014-08-18  XXXX      2
2015-01-10  XXXX      3
2015-01-20  XXXX      4
2014-08-21  XXXX      5
2014-08-22  XXXX      2
2014-01-23  XXXX      3
2014-08-24  XXXX      2
2014-02-25  XXXX      3
2014-08-26  XXXX      2
2014-06-27  XXXX      4
2014-08-28  XXXX      1
2014-08-29  XXXX      1
2015-08-30  XXXX      2
2015-09-31  XXXX      3

目标是通过上面给出的公式计算 2014 年至 2015 年间每 28 天的流失率。因此,它将通过将数据滚动 28 天并通过公式计算流失来聚合数据。

这是我尝试按日期范围汇总数据的内容:

SELECT COUNT(distinct customer_id) AS count_ids, Group,
        DATE_SUB(CAST(Date AS DATE), INTERVAL 56 DAY) AS Date_min,
        DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY) AS Date_max
 FROM churn_agg
 GROUP BY count_ids, Group, Date_min, Date_max

希望有人能帮助我进行聚合和流失计算。我想简单地扣除聚合的 count_ids 以从 28 天后的下一个聚合的 count_ids 中扣除。所以这将是连续扣除相同的列值(count_ids)。我不确定是否必须使用滚动窗口或简单聚合来查找流失。

【问题讨论】:

  • 你也在 postgresql 工作?
  • 这是一个演示:dbfiddle.uk/… 也许它会对某人有所帮助,我不明白 OP 想要什么......
  • 样本数据很好,但也需要(匹配的)预期结果。
  • 您需要一个帮助表(或 cte),其中包含 2014 年至 2015 年之间每 28 天的开始和结束日期。外部联接。
  • @jarlh,感谢您的评论。我可以创建 cte 表,但是,我需要有关按 28 天聚合它的逻辑方面的帮助。

标签: sql aggregation


【解决方案1】:

正如@jarlh 所纠正,不是 2015-09-31 而是 2015-09-30 您可以使用它来创建 28 天日历:

create table daysby28  (i int, _Date date);
insert into daysby28  (i, _Date)
SELECT i, cast('01-01-2014'as date) + i*INTERVAL '28 day'
from generate_series(0,50) i
order by 1;

在你使用他用小提琴发送的@jarlh churn_agg 表创建之后,通过这个查询,你得到你想要的:

with cte as
(
  select count(Customer) as TotalCustomer, Cohort, CohortDateStart From
  (  
    select distinct a.Customer_id as Customer, b.i as Cohort, b._Date as CohortDateStart
    from churn_agg a left join daysby28 b on a._Date >=  b._Date and a._Date <  b._Date + INTERVAL '28 day' 
  ) a
  group by Cohort, CohortDateStart
)
select a.CohortDateStart, 
1.0*(b.TotalCustomer - a.TotalCustomer)/(1.0*b.TotalCustomer) as Churn from cte a
left join cte b on a.cohort > b.cohort
and not exists(select 1 from cte c where c.cohort > b.cohort and c.cohort < a.cohort)
order by 1  

大家的小提琴是here

【讨论】:

    猜你喜欢
    • 2018-09-02
    • 2020-01-04
    • 2023-04-05
    • 1970-01-01
    • 2020-05-09
    • 2013-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多