查找过去 X 天内的活跃客户

Posted

技术标签:

【中文标题】查找过去 X 天内的活跃客户【英文标题】:Find Active customers in past X days 【发布时间】:2020-12-17 14:46:43 【问题描述】:

我正面临一些困难时期,需要快速帮助。如果有人可以帮助我,那就太好了。 提前非常感谢:)

我有 2 张桌子。 第一张表:daily_customer_snapshot:客户的每日快照,如下图所示。

c_id date state location
b1 2020-12-01 Active OOW
b1 2020-12-02 Active OOW
b1 2020-12-03 Active OOW
b1 2020-12-04 Active OOW
b1 2020-12-05 Active OOW
b3 2020-12-06 Active OOW
b3 2020-12-07 Active OOW
b3 2020-12-08 Active OOW
b1 2020-12-09 Decay IW
b2 2020-12-15 Active OOW

第二个表:customer_date_series:包含从用户成为我们的客户之日起的日期系列。 例如:参考图片 2:用户 b1 在“2020-12-01”成为我们的客户,用户 b3 在“2​​020-12-06”成为我们的客户 b2 于 '2020-12-15' 成为我们的客户。我已经生成了带有 customer_id 的日期系列,以计算在任何给定日期我们有多少客户。

c_id date
b1 2020-12-01
b1 2020-12-02
b1 2020-12-03
b1 2020-12-04
b1 2020-12-05
b1 2020-12-06
b1 2020-12-07
b1 2020-12-08
b1 2020-12-09
b1 2020-12-10
b1 2020-12-11
b1 2020-12-12
b1 2020-12-13
b1 2020-12-14
b1 2020-12-15
b1 2020-12-16
b3 2020-12-06
b3 2020-12-07
b3 2020-12-08
b3 2020-12-09
b3 2020-12-10
b3 2020-12-11
b3 2020-12-12
b3 2020-12-13
b3 2020-12-14
b3 2020-12-15
b3 2020-12-16
b2 2020-12-15
b2 2020-12-16

我将 table1 (customer_date_series) 与 table2 (daily_customer_snapshot) 连接在一起,以获取任何给定日期的客户行为概览。 我得到了如图 3 所示的结果。

查询加入:

    select 
    bds.date,
    bds.c_id,
    b.state,
    b.location
    
FROM
    customer_date_series bds LEFT JOIN daily_customer_snapshot b ON bds.c_id = b.c_id and bds.date = b.date
ORDER BY
    1,2; 
date c_id state location
2020-12-01 b1 Active OOW
2020-12-02 b1 Active OOW
2020-12-03 b1 Active OOW
2020-12-04 b1 Active OOW
2020-12-05 b1 Active OOW
2020-12-06 b1
2020-12-06 b3 Active OOW
2020-12-07 b1
2020-12-07 b3 Active OOW
2020-12-08 b1
2020-12-08 b3 Active OOW
2020-12-09 b1 Decay IW
2020-12-09 b3
2020-12-10 b1
2020-12-10 b3
2020-12-11 b1
2020-12-11 b3
2020-12-12 b1
2020-12-12 b3
2020-12-13 b1
2020-12-13 b3
2020-12-14 b1
2020-12-14 b3
2020-12-15 b1
2020-12-15 b2 Active OOW
2020-12-15 b3
2020-12-16 b1
2020-12-16 b2
2020-12-16 b3

这是我苦苦挣扎的地方。 我在这里面临挑战。我想创建名为“状态”的新列,如果daily_customer_snapshot 中的客户数据在current_date 的过去5 天内更新 我想将状态设置为“活动”,否则为“不活动”。 前任:

【问题讨论】:

请阅读this,了解一些改进问题的技巧。不要发布数据图像,使用文本。您需要一个适用于mysqlpostgresql tsql 的答案吗?如果没有,则删除不适当的标签。 Postgres 还是 Redshift?尽管它们有着一些古老的渊源,但它们是截然不同的产品。 Redshift 是 @a_horse_with_no_name ,如果有人能给出更优化的解决方案,那就太好了。 【参考方案1】:

如果我没看错,你可以使用布尔窗口聚合:

select 
    bds.date,
    bds.c_id,
    b.state,
    b.location,
    bool_or(b.state = 'Active') over(
        partition by bds.c_id 
        order by bds.date 
        range between interval '5 days' preceding and current row
    ) as is_active
from customer_date_series bds 
left join daily_customer_snapshot b on bds.c_id = b.c_id and bds.date = b.date 
order by 1,2;

这会在同一客户在过去 5 天(或当天)内至少活跃一次的行上设置一个布尔标志。

如果您确实想查看 'Active'/ 'InActive'(我发现它不如布尔值有用),您可以这样做:

    min(b.state) over(
        partition by bds.c_id 
        order by bds.date 
        range between interval '5 days' preceding and current row
    ) as status

... 这行得通,因为字符串方面,'Active' < 'InActive'

【讨论】:

嗨@GMB,非常感谢您的帮助。无论客户的状态(不仅需要活跃,也可以衰减)是什么,如果我们在过去 5 天的快照中输入了数据,则 customer_status 设置为“活跃”,否则设置为“不活跃”。对于状态列下的每个电池,我必须为每个日期输入 1 个条目。 @SidduKattimani:所以,我们可以这样做:bool_or(b.c_id is not null) over(...) 但是我们可以不创建一个新列“状态”,我们可以将值设置为“活动”或“非活动”,如结果屏幕截图中所述吗? @GMB @SidduKattimani:我不建议存储这些派生信息。您可以使用查询即时计算它。或者,如果您将定期需要它,您可以创建一个视图。【参考方案2】:

如果您想同时使用这两个表,那么横向连接就可以满足您的需求:

select bds.date, bds.c_id, b.state, b.location
--CASE WHEN b.state = '%ActiveDecay%' between current_date- 10 and current_date THEN 'ActIve' ELSE 'DECAY' END as STATUS
FROM battery_date_series bds LEFT JOIN LATERAL
     (SELECT b.*
      FROM battery b 
      WHERE bds.c_id = b.c_id and b.date <= bds.date
      ORDER BY b.date DESC
      LIMIT 1
     ) b
     ON 1=1
ORDER BY 1,2;

【讨论】:

我不想更新状态列,我想要一个名为“状态”的新列,如果我们在过去 5 中为快照表中的特定 c_id 输入了数据从当前日期开始的天数,则必须将其设置为“活动”,否则为“不活动”。不过,感谢您的回复:)

以上是关于查找过去 X 天内的活跃客户的主要内容,如果未能解决你的问题,请参考以下文章

找出哪些客户在 10 天内购买了超过 75 美元的商品

SQL Server:如何为同一张表中的不同客户获取 3 天内的滚动总和

支付机构MRC模型

统计过去 7 天内的类似事件

MySql 我如何返回过去 60 天和不在 60 天内的多个特定 ID?

SQL:查找锁定日期的棘手问题