3716. 寻找流失风险客户
题目描述
表:subscription_events
+------------------+---------+ | Column Name | Type | +------------------+---------+ | event_id | int | | user_id | int | | event_date | date | | event_type | varchar | | plan_name | varchar | | monthly_amount | decimal | +------------------+---------+ event_id 是这张表的唯一主键。 event_type 可以是 start,upgrade,downgrade 或 cancel。 plan_name 可以是 basic,standard,premium 或 NULL(当 event_type 是 cancel)。 monthly_amount 表示此次事件后的月度订阅费用。 对于 cancel 的事件,monthly_amount 为 0。
编写一个解决方案来 寻找流失风险用户 - 出现预流失信号的用户。如果用户符合以下所有条件,则被视为 有流失风险 的客户:
- 目前有 有效的订阅(他们的最后事件不是 cancel)。
- 已在其订阅历史中 至少进行过一次 降级。
- 他们 目前的订阅费用 低于历史最高订阅费用的
50%
。 - 已订阅 至少
60
天。
返回结果表按 days_as_subscriber
降序 排序,然后按 user_id
升序 排序。
结果格式如下所示。
示例:
输入:
subscription_events 表:
+----------+---------+------------+------------+-----------+----------------+ | event_id | user_id | event_date | event_type | plan_name | monthly_amount | +----------+---------+------------+------------+-----------+----------------+ | 1 | 501 | 2024-01-01 | start | premium | 29.99 | | 2 | 501 | 2024-02-15 | downgrade | standard | 19.99 | | 3 | 501 | 2024-03-20 | downgrade | basic | 9.99 | | 4 | 502 | 2024-01-05 | start | standard | 19.99 | | 5 | 502 | 2024-02-10 | upgrade | premium | 29.99 | | 6 | 502 | 2024-03-15 | downgrade | basic | 9.99 | | 7 | 503 | 2024-01-10 | start | basic | 9.99 | | 8 | 503 | 2024-02-20 | upgrade | standard | 19.99 | | 9 | 503 | 2024-03-25 | upgrade | premium | 29.99 | | 10 | 504 | 2024-01-15 | start | premium | 29.99 | | 11 | 504 | 2024-03-01 | downgrade | standard | 19.99 | | 12 | 504 | 2024-03-30 | cancel | NULL | 0.00 | | 13 | 505 | 2024-02-01 | start | basic | 9.99 | | 14 | 505 | 2024-02-28 | upgrade | standard | 19.99 | | 15 | 506 | 2024-01-20 | start | premium | 29.99 | | 16 | 506 | 2024-03-10 | downgrade | basic | 9.99 | +----------+---------+------------+------------+-----------+----------------+
输出:
+----------+--------------+------------------------+-----------------------+--------------------+ | user_id | current_plan | current_monthly_amount | max_historical_amount | days_as_subscriber | +----------+--------------+------------------------+-----------------------+--------------------+ | 501 | basic | 9.99 | 29.99 | 79 | | 502 | basic | 9.99 | 29.99 | 69 | +----------+--------------+------------------------+-----------------------+--------------------+
解释:
- 用户 501:
- 当前订阅有效:最近一次事件是降级到基础(未取消)
- 有降级记录:是,历史上有 2 次降级
- 当前订阅(9.99)vs 最大订阅(29.99):9.99/29.99 = 33.3%(少于 50%)
- 订阅天数:1 月 1 日到 5 月 20 日 = 79 天(至少 60 天)
- 结果:流失风险客户
- 用户 502:
- 当前订阅有效:最近一次事件是降级到基础(未取消)
- 有降级记录:是,历史上有 1 次降级
- 当前订阅(9.99)vs 最大订阅(29.99):9.99/29.99 = 33.3%(少于 50%)
- 订阅天数:1 月 5 日到 5 月 15 日 = 70 天(至少 60 天)
- 结果:流失风险客户
- 用户 503:
- 当前订阅有效:最近一次事件是升级到高级(未取消)
- 有降级记录:历史上没有降级
- 结果:无风险客户(没有降级历史)
- 用户 504:
- 当前订阅有效:最近一次事件是取消
- 结果:无风险客户(已取消订阅)
- 用户 505:
- 当前订阅有效:最近一次事件是升级到标准(未取消)
- 有降级记录:历史上没有降级
- 结果:无风险客户(没有降级历史)
- 用户 506:
- 当前订阅有效:最近一次事件是降级到标准(未取消)
- 有降级记录:是,历史上有 1 次降级
- 当前订阅(9.99)vs 最大订阅(29.99):9.99/29.99 = 33.3%(少于 50%)
- 订阅天数:1 月 20 日到 5 月 10 日 = 50 天(少于 60 天)
- 结果:无风险客户(订阅时长不足)
结果表按 days_as_subscriber 降序排序,然后按 user_id 升序排序。
注意:days_as_subscriber 按照每个用户的第一个事件日期到最后一个事件日期进行计算。
解法
方法一:分组统计 + 连接 + 条件筛选
我们先通过窗口函数获取每个用户按照事件日期和事件 ID 降序排列的最后一条记录,得到每个用户的最新事件信息。然后,我们通过分组统计每个用户的订阅历史信息,包括订阅开始日期、最后事件日期、历史最高订阅费用以及降级事件的数量。最后,我们将最新事件信息与历史统计信息进行连接,并根据题目要求的条件进行筛选,得到流失风险客户列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
|