按周显示的滚动尾随 30 天窗口中的唯一客户总数

Posted

技术标签:

【中文标题】按周显示的滚动尾随 30 天窗口中的唯一客户总数【英文标题】:Sum of unique customers in rolling trailing 30d window displayed by week 【发布时间】:2020-12-27 02:45:43 【问题描述】:

我在 SQL Workbench 中工作。

我想跟踪过去 30 天内每次有唯一身份客户点击新功能的时间,每周显示一次。数据输出示例如下:

第 51 周:反映到第 51 周(12 月 20 日)结束 - 30 天的使用情况。又名 11 月 20 日至 12 月 20 日 第 52 周:反映到第 52 周(12 月 31 日)结束 - 30 天的使用情况。也就是 12 月 1 日 - 12 月 31 日。

假设在 11 月 20 日至 12 月 20 日期间发生了 22MM 的唯一客户点击。第 51 周数据 = 22MM。 假设在 12 月 1 日至 12 月 31 日期间发生了 25MM 的唯一客户点击。第 52 周数据 = 25MM。客户唯一性仅与该特定周相关。 Aka,如果客户在第 51 周点击两次,他们只会被计算一次。如果他们在第 51 周和第 52 周点击一次,则每周计算一次。

这是我目前所拥有的:

select 
         min_e_date
        ,sum(count(*)) over (order by min_e_date rows between unbounded preceding and current row) as running_distinct_customers
from (select customer_id, min(DATE_TRUNC('week', event_date)) as min_e_date
        from final
        group by 1
      ) c
group by 
          min_e_date

我认为滚动计数不是正确的方法。当我添加其他参数(国家、订阅)时,滚动计数不会区分它们 - 数字只是被添加到前一行。

欢迎提出任何建议!

编辑下面的其他数据。数据收集于 11/23 开始。该日期之前没有数据。

【问题讨论】:

样本数据和期望的结果将真正阐明您想要做什么。 抱歉@liebhabe,您的要求不够明确。需要样本数据和期望的输出作为例子 @GordonLinoff 谢谢 - 附加数据附加到原始帖子。 @Raihan 谢谢 - 附加数据附加到原始帖子。 【参考方案1】:

您可以像这样获得每周不同客户的数量:

select date_trunc('week', event_date) as week_start, 
    count(distinct customer_id) cnt 
from final
group by 1

现在,如果您想要该计数的滚动总和(例如,当前周和前三周),您可以使用窗口函数:

select date_trunc('week', event_date) as week_start, 
    count(distinct customer_id) cnt,
    sum(count(distinct customer_id)) over(
        order by date_trunc('week', event_date)
        range between 3 week preceding and current row
    ) as rolling_cnt
from final
group by 1

【讨论】:

谢谢,已经结束了。每周需要计算前几周内最多 30 天的所有唯一客户。我附上了其他数据,希望可以澄清我的问题。在您的答案中,它是每周计算唯一客户,然后每周添加他们(滚动计数)。我每周都在寻找过去 30 天内的唯一客户。【参考方案2】:

在 RedShift 中滚动不同的计数非常困难。一种方法是自联接和聚合:

select t.date,
       count(distinct case when tprev.date >= t.date - interval '6 day' then customer_id end) as trailing_7,
       count(distinct customer_id) as trailing_30
from t join
     t tprev
     on tprev.date >= t.date - interval '29 day' and
        tprev.date <= t.date
group by t.date;

如果你可以让它工作,你可以选择每 7 行来获取每周值。

编辑:

一种完全不同的方法是使用聚合并跟踪客户何时进入和结束被计算的时间段。这是两个不同时间框架的痛苦。这是一个人的样子。

这个想法是

    为每个被计算的记录创建一个进入/退出记录。 “退出”是在进入后 n 天。 将这些总结为每个客户的活动周期。因此,有一个记录有进入和退出日期。这是一种孤岛问题。 取消透视此结果以计数 +1 表示正在计数的客户和 -1 表示未计数的客户。 做这个计数的累积和。

代码如下所示:

with cd as (
      select customer_id, date,
             lead(date) over (partition by customer_id order by date) as next_date,
             sum(sum(inc)) over (partition by customer_id order by date) as cnt
      from ((select t.customer_id, t.date, 1 as inc
             from t
            ) union all
            (select t.customer_id, t.date + interval '7 day', -1
             from t
            )
           ) tt
     ),
     cd2 as (
      select customer_id, min(date) as enter_date, max(date) as exit_date
      from (select cd.*,
                   sum(case when cnt = 0 then 1 else 0 end) over (partition by customer_id order by date) as grp
            from (select cd.*,
                         lag(cnt) over (partition by customer_id order by date) as prev_cnt
                  from cd
                 ) cd
           ) cd
      group by customer_id, grp
      having max(cnt) > 0
     )
select dte, sum(sum(inc)) over (order by dte)
from ((select customer_id, enter_date as dte, 1 as inc
       from cd2
      ) union all
      (select customer_id, exit_date as dte, -1 as inc
       from cd2
      )
     ) cd2
group by dte;
      

【讨论】:

谢谢,现在就试试。工作台一直超时。这似乎是一个困难的要求……一个真正令人头疼的问题。我很好奇这种类型的请求多久会出现一次。我最初的计划是每周汇总唯一客户,并每周显示数据。 @liebhabe 。 . .有一种完全不同的方法。但这是两个不同时间框架的痛苦。

以上是关于按周显示的滚动尾随 30 天窗口中的唯一客户总数的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 中的窗口函数尾随日期

米兰达聊天窗口中的状态更改消息

如何在php中按周显示网格中的天数?

有一种系统天窗叫模块化智能天窗

如何对数据进行分组以从选择查询中按周显示平均价格

在 Presto 中为多个功能重复相同的窗口?