需求
以周为单位,三周为一个跟踪周期来计算每周会员留存率。例如 2018 第 23 周的留存率需要计算出如下的结果:
23周 | 24 周 | 25 周 |
---|---|---|
50 个会员 | 23 个会员 | 24 个会员 |
方法1
利用子查询的方式来计算每周的留存率。类似下面的 sql
select 'week1' as week_num
,count(distinct week1.member_id) as week1_member_num
,count(distinct week2.member_id) as week2_member_num
,count(distinct week3.member_id) as week3_member_num
from (
select member_id
, order_id
from fct_order
where date betwenn 'week1_monday' and 'week1_sunday'
) as week1
left join (
select member_id
, order_id
from fct_order
where date betwenn 'week2_monday' and 'week2_sunday'
) as week2
on week2.member_id = week1.member2
left join (
select member_id
, order_id
from fct_order
where date betwenn 'week3_monday' and 'week3_sunday'
) as week3
on week3.member_id = week1.member2
这个方法的缺点:
- 一次只能计算一周的留存,不能一次性计算出多周的数据
- 跟踪的周期变长后,计算效率低会很低
方法2
可以先给一个周期内的会员打标签。我们可以使用 case when 来判断没周内是否有消费记录,例如,一个会员 A 分别在 23、24 周内有消费记录,25 周没有,可以使用如下的 类似的 sql 进行打标签:
select member_id
max(if(date between 'week1_monday' and 'week1_sunday',1,0 )) as week1_consumption
,max(if(date between 'week2_monday' and 'week2_sunday',1,0 )) as week2_consumption
,max(if(date between 'week3_monday' and 'week3_sunday',1,0 )) as week3_consumption
from fct_order
where date between 'week1_monday' and 'week3_sunday'
会员 A 可以得到下面的结果:
member_id | week1_consumption | week2_consumption | week3_consumption |
---|---|---|---|
A | 1 | 1 | 0 |
把会员的标签数据放到一个临时(tmp_member_flag)表里面最后计算三周的情况:
select week_num
,count(distinct if(flag.week1_consumption=1,member_id,null)) as '第一周的会员数'
,sum(if(flag.week1_consumption=1,sale_amt,0)) as '第一周会员消费额'
,count(distinct if(flag.week1_consumption=1 and flag.week2_consumption=1
,member_id,null)) as '第二周的会员留存数'
,sum(if(flag.week1_consumption=1 and flag.week1_consumption=1
,sale_amt,0)) as '第二周留存会员消费额'
,count(distinct if(flag.week1_consumption=1
and flag.week2_consumption=1
and flag.week3_consumption=1
,member_id,null)) as '第三周的会员留存数'
,sum(if(flag.week1_consumption=1
and flag.week2_consumption=1
and flag.week3_consumption=1
,sale_amt,0)) as '第三周留存会员消费额'
,count(distinct if(flag.week1_consumption=0
and flag.week2_consumption=1
,member_id,null)) as '第二周的新会员'
,sum(if(flag.week1_consumption=0
and flag.week2_consumption=1
,sale_amt,0)) as '第二周新会员消费额'
,count(distinct if(flag.week1_consumption=0
and flag.week2_consumption=1
and flag.week3_consumption=1
,member_id,null)) as '第二周在第三周的留存数'
,sum(if(flag.week1_consumption=0
and flag.week2_consumption=1
and flag.week3_consumption=1
,sale_amt,0)) as '第二周在第三周留存会员消费额'
from fct_order as order
left join tmp_member_flag as flag
on order.member_id = flag.member_id
where date between 'week1_monday' and 'week3_sunday'
这样可以一次计算出三周的留率