背景:
在日常分析用户行为时,经常会碰到想要知道,比如:
每隔多久会购买一次某物品;每隔多少天会发生一次购物;每隔多久会使用某功能;
每次进入某APP看几个商品会下单;每隔多久资金会回转;
某事发生多久后会发生另一个事件,等等看起来是2个事件或多个事件之间间隔时长,间隔事件次数的分析。
针对用户的的“需求周期”可以针对性的做触达,或激励,想消费者所想,并帮助提升转化。

上海疫情居家60天。仅以此图致敬阳光灿烂的日子
01
—
常见的“间隔”场景
本文针对诸如以上的“间隔分析”场景做以下总结:
「每隔多少天发生某事件」-回购周期-间隔天数(间隔时长)
「每隔多少天发生某事件」—同一天购买多次算一次-间隔天数(间隔时长)
「每隔多少天发生某事件」—连续多天发生算一次--间隔天数(间隔时长)
「每发生多少个A,会发生B事件」。每次购买前浏览商品次数---间隔次数
「连续发生B后会经历多少天A再次发生B」,「连续发生B后会经历多少个A再次发生B」
「每发生A后,发生多少个C,会发生B」。每个包含A和C的回合中,有多少个B发生
「连续多少天发生某事件」
「发生A事件后,多久发生B事件」。最后一个A往后找最近的一个B。视频播放时长。时长次均值。人均值。
「发生A事件后,多久发生B事件」。第一个A往后找最近的一个B。
「发生A事件后,多久发生B事件」。每一个A往后找最近的一个B。取平均时长为间隔时长。

喜欢大海的包容,看一下海,心潮澎湃
02
—
“间隔”场景详情及分析思路
1.「每隔多少天发生某事件」-回购周期-间隔天数(间隔时长)
场景:距上次购买多少天后发生购买,计算回购周期天数或时长。
思路:1).找到每个A。
select d.rebuycircle,count(distinct d.user_id) as user_amountsfrom(select c.user_id,round(avg(days),0) as rebuycirclefrom(select b.user_id,datediff(b.lastpurtime,b.time) as daysfrom(select tt.*,LEAD(tt.time)over(partition by tt.user_id order by tt.time) as lastpurtimefrom(select t.user_id,t.time,t.order_id,a.pay_freqfrom(select user_id,time,event,order_id from events where event='PayOrder' order by time)t left join(select user_id,event,count(order_id) as pay_freq from events where event='PayOrder' group by user_id,event having count(order_id)>=2) aon t.user_id=a.user_idwhere a.user_id is not null)ttorder by tt.user_id,tt.time) b)cgroup by c.user_id) dgroup by d.rebuycircleorder by d.rebuycircle
2.「每隔多少天发生某事件」—同一天购买多次算一次-间隔天数(间隔时长)
场景:距上次购买多少天后发生购买,计算回购周期天数或时长。同一天可能购买多次,可能是因为多次下单,当天购买不代表当天需求多次。同一天购买多次算一次需求,计算需求周期。
思路:1).找到用户发生的A事件和日期,按照用户,事件和日期去重。
##回购天数。同一天购买多次算一次-购买的间隔天数。select d.rebuycircle,count(distinct d.user_id) as user_amountsfrom(select c.user_id,round(avg(days),0) as rebuycirclefrom(select b.user_id,datediff(b.lastpurtime,b.date) as daysfrom(select tt.*,LEAD(tt.date)over(partition by tt.user_id order by tt.date) as lastpurtimefrom(select t.user_id,t.date,a.pay_freqfrom(select distinct user_id,date,event from events where event='PayOrder')t left join(select user_id,event,count(distinct date) as pay_freq from events where event='PayOrder'group by user_id,event having count(distinct date)>=2) aon t.user_id=a.user_idwhere a.user_id is not null)ttorder by tt.user_id,tt.date) b)cgroup by c.user_id) dgroup by d.rebuycircleorder by d.rebuycircle
3.「每隔多少天发生某事件」—连续多天发生算一次--间隔天数(间隔时长)
场景:用户需求间隔。某跨境电商ERP系统中,用户平均多少天会再次使用发货功能,供应链模块。此种场景可能会连续多天使用某功能,当连续多天使用时按一次需求。计算对某功能的需求周期。
思路:1).找到A事件,计算每2个A事件之间的间隔天数。
select a.user_id,round(avg(datediff),0) as rebuycircle from(select a.user_id,a.date,datediff from(selecta.user_id,a.date,lead(a.date,1) over ( partition by a.user_id order by a.date asc),datediff(lead(a.date,1) over ( partition by a.user_id order by a.date asc ),date) as datedifffrom(select distinct user_id,date,event from events where event='PayOrder' order by user_id,date)a)a where datediff>1)agroup by a.user_id
4.「每发生多少个A,会发生B事件」。每次购买前浏览商品次数---间隔次数
场景:每次购买前需要浏览多少次商品。
思路:1).找到每个B。
selecta.user_id,a.num,if(a.num=1,a.num1,a.num1-b.num2) as cishu from(select b.user_id,b.num,count(a.user_id) as num1from(Select user_id,event,timefrom events where event='CommodityDetail')aright join(Select user_id,event,time, count(*) OVER(PARTITION BY user_id ORDER BY time asc) as numfrom events where event='PayOrder')bon a.user_id=b.user_id and a.time<b.timegroup by b.user_id,b.num order by b.user_id,b.num asc)aleft join(select b.user_id,b.num,count(a.user_id) as num2from(Select user_id,event,timefrom events where event='CommodityDetail')aright join(Select user_id,event,time, count(*) OVER(PARTITION BY user_id ORDER BY time asc) as numfrom events where event='PayOrder')bon a.user_id=b.user_id and a.time<b.timegroup by b.user_id,b.num order by b.user_id,b.num asc)bon a.user_id=b.user_id and a.num=b.num+1order by a.user_id,a.num asc

5.「连续发生B后会经历多少天A再次发生B」,「连续发生B后会经历多少个A再次发生B」
资产周期天数~用户每次从低于100回转的周期天数
B后第一个A开始,和A出现后首个B的时间间隔。其实还是BB之间的间隔天数。只是初始取第一个B后的A时间。
思路1:1).找到每个B,并计算B后每隔间隔时长。
2).找到每隔B后出现的A的次数。
3).筛选出B后A次数大于0的B的间隔天数
思路2:见资产周期天数。SQL计算资产周期天数难么?只需要6步?
#思路1#select a.user_id,avg(datediff) as avg_datefrom(select a.user_id,a.stat_date,a.end_date,a.datediff,count(b.user_id)from(select a.user_id,a.stat_date ,a.user_asset_total,lead(a.stat_date,1) over ( partition by a.user_id order by a.stat_date asc) as end_date,datediff(lead(a.stat_date,1) over ( partition by a.user_id order by a.stat_date asc ),stat_date)+1 as datedifffrom(select a.user_id,a.stat_date as stat_date ,a.user_asset_total from(select user_id,stat_date,user_asset_total,if(user_asset_total>100,1,0) as 'is_100'from asset a)awhere a.is_100=1)a)aleft join(select a.user_id,a.stat_date,a.user_asset_total from(select user_id,stat_date,user_asset_total,if(user_asset_total>100,1,0) as 'is_100'from asset a)awhere a.is_100=0)bon b.user_id=a.user_id and b.stat_date>=a.stat_date and b.stat_date<=a.end_dategroup by a.user_id,a.stat_date,a.end_date,a.datediff having count(b.user_id)>0)agroup by a.user_id
6.「每发生A后,发生多少个C,会发生B」。每个包含A和C的回合中,有多少个B发生
场景:某咖啡/快餐APP,每次启动/进入菜单后,浏览多少个商品后下单。每个包含A和C的回合中,有多少个B发生
思路:1).先找到每个A去排序。
select d.user_id,avg(c_cishu) as avg_cishu from(select ab.user_id,ab.a_time,ab.b_time,count(c.user_id) as c_cishu from(select a.user_id,a.a_time,min(b_time) as b_time from(select user_id,event,time as a_time, row_number() over (PARTITION BY user_id ORDER BY time ASC) as row_num,lead(time,1) OVER (PARTITION BY user_id ORDER BY time ASC) as a_time_end from events where event='$AppStart')aleft join(select user_id,event,time as b_time from events where event='PayOrder')bon a.user_id=b.user_id and b.b_time<a_time_end and b.b_time>a_timewhere b.b_time is not nullgroup by a.user_id,a.a_time)ableft join(select user_id,event,time as c_time from events where event='CommodityDetail')con ab.user_id=c.user_id and c.c_time<ab.b_time and c.c_time>ab.a_timegroup by ab.user_id,ab.a_time)dgroup by d.user_id
7.「连续多少天发生某事件」
连续多少天发生A事件的用户及天数。
#连续2天及以上购物的用户及其天数#select user_id,ymd-rn,count(*) dayscountfrom(select user_id, datediff(date,'1970-01-01’) ymd,row_number()over (partition by user_id order by date) rnFrom events)aGroup by user_id,ymd-rnhaving count(*)>1
8.「发生A事件后,多久发生B事件」。最后一个A往后找最近的一个B。视频播放时长。时长次均值。人均值。
场景:观看视频时,发生视频开始,暂停,开始,开始,恢复,结束等事件。每次在暂停或结束时计算时长,如果在结束或暂停时前边一个事件也是暂停或结束,则时长不计算。诸如此类的ABCB事件,可转化为ABAB事件。当ABAABBAB发生时,只考虑2个不交叉的AB,从A到B之间的时长。
思路:1).找到AB事件。
select a.user_id,round(sum(timediff)/60) as sum_mins,round(avg(timediff)/60) as avg_minsfrom(selecta.user_id,event,time,timestampdiff(second,a.start_time,time) as timedifffrom(select user_id,event,time,lag(event,1) over (partition by user_id order by time) as start_event,lag(time,1) over (partition by user_id order by time) as start_timefrom(select user_id,event,time from events2 where event in ('start' ,'end'))a)awhere start_event='start' and event='end')a group by a.user_id
9.「发生A事件后,多久发生B事件」。第一个A往后找最近的一个B。
场景:首次发生B的时间间隔。比如首次点击「立即开户」后多久完成「开户成功」。首次登录到首次付费的时间间隔。
思路:1).找到用户发生的第一个A事件,第一个B事件。
select a.user_id,a.start_time,b.end_time,timestampdiff(second,a.start_time,b.end_time) as timediff,datediff(a.start_time,b.end_time) as datedifffrom(select user_id,min(time) as start_time from events2 where event='start' group by user_id)aleft join(select user_id,min(time) as end_time from events2 where event='end' group by user_id)bon a.user_id=b.user_id
10.「发生A事件后,多久发生B事件」。每一个A往后找最近的一个B。取平均时长为间隔时长
思路:1).找到用户发生的每一个A事件,
select a.user_id,round(avg(timediff)) as avgtimediff from(select a.user_id,end_time,avg(timediff) as timedifffrom(#计算每个A到最近的B的时长#select a.user_id,end_time,timestampdiff(second,a.start_time,end_time) as timedifffrom(select a.user_id,a.start_time,min(end_time) as end_timefrom(select user_id,time as start_time from events2 where event='start' )aleft join(select user_id,time as end_time from events2 where event='end')bon a.user_id=b.user_id and b.end_time>a.start_time group by a.user_id,a.start_time)a#计算每个A到最近的B的时长#)agroup by a.user_id,end_time)a group by a.user_id

欢迎一起探讨好玩的分析和查询命题,或者数据驱动增长的话题,有兴趣可私聊加微:joy691508。疫情之下,愿大家心情愉悦~望上海早日解封~




