连续登陆问题案例

连续登陆问题案例

在电商、物流和银行可能经常会遇到这样的需求:统计用户连续交易的总额、连续登陆天数、连续登陆开始和结束时间、间隔天数等

数据:

注意:每个用户每天可能会有多条记录

amount表示金额

id	datestr	  amount

1,2019-02-08,6214.23 
1,2019-02-08,6247.32 
1,2019-02-09,85.63 
1,2019-02-09,967.36 
1,2019-02-10,85.69 
1,2019-02-12,769.85 
1,2019-02-13,943.86 
1,2019-02-14,538.42
1,2019-02-15,369.76
1,2019-02-16,369.76
1,2019-02-18,795.15
1,2019-02-19,715.65
1,2019-02-21,537.71
2,2019-02-08,6214.23 
2,2019-02-08,6247.32 
2,2019-02-09,85.63 
2,2019-02-09,967.36 
2,2019-02-10,85.69 
2,2019-02-12,769.85 
2,2019-02-13,943.86 
2,2019-02-14,943.18
2,2019-02-15,369.76
2,2019-02-18,795.15
2,2019-02-19,715.65
2,2019-02-21,537.71
3,2019-02-08,6214.23 
3,2019-02-08,6247.32 
3,2019-02-09,85.63 
3,2019-02-09,967.36 
3,2019-02-10,85.69 
3,2019-02-12,769.85 
3,2019-02-13,943.86 
3,2019-02-14,276.81
3,2019-02-15,369.76
3,2019-02-16,369.76
3,2019-02-18,795.15
3,2019-02-19,715.65
3,2019-02-21,537.71
建表语句
create table deal_tb(
    id string
    ,datestr string
    ,amount string
)row format delimited fields terminated by ',';
计算逻辑
  • 统计连续交易,日期不能重复

    先按用户和日期分组求和,使每个用户每天只有一条数据

 select  id
         ,datestr
         ,sum(amount) as sum_amount
 from deal_tb
 group by id,datestr;
 
 //执行结果
1	2019-02-08	12461.55
1	2019-02-09	1052.99
1	2019-02-10	85.69
1	2019-02-12	769.85
1	2019-02-13	943.86
1	2019-02-14	538.42
1	2019-02-15	369.76
1	2019-02-16	369.76
1	2019-02-18	795.15
1	2019-02-19	715.65
1	2019-02-21	537.71
2	2019-02-08	12461.55
2	2019-02-09	1052.99
2	2019-02-10	85.69
2	2019-02-12	769.85
2	2019-02-13	943.86
2	2019-02-14	943.18
2	2019-02-15	369.76
2	2019-02-18	795.15
2	2019-02-19	715.65
2	2019-02-21	537.71
3	2019-02-08	12461.55
3	2019-02-09	1052.99
3	2019-02-10	85.69
3	2019-02-12	769.85
3	2019-02-13	943.86
3	2019-02-14	276.81
3	2019-02-15	369.76
3	2019-02-16	369.76
3	2019-02-18	795.15
3	2019-02-19	715.65
3	2019-02-21	537.71
  • 想要求连续交易总额,日期要转换为一样的,才能进行分组求和

    根据用户ID分组,使用row_number()给日期编号,从上到下1、2、3...,

    select t1.id
           ,t1.datestr
           ,t1.sum_amount
           ,row_number() over(partition by id order by datestr) as rn
    from  (
         select  id
             ,datestr
             ,sum(amount) as sum_amount
     from deal_tb
     group by id,datestr
    ) t1;
    
    //执行结果
    1	2019-02-08	12461.55	1
    1	2019-02-09	1052.99		2
    1	2019-02-10	85.69		3
    1	2019-02-12	769.85		4
    1	2019-02-13	943.86		5
    1	2019-02-14	538.42		6
    1	2019-02-15	369.76		7
    1	2019-02-16	369.76		8
    1	2019-02-18	795.15		9
    1	2019-02-19	715.65		10
    1	2019-02-21	537.71		11
    2	2019-02-08	12461.55	1
    2	2019-02-09	1052.99		2
    2	2019-02-10	85.69		3
    2	2019-02-12	769.85		4
    2	2019-02-13	943.86		5
    2	2019-02-14	943.18		6
    2	2019-02-15	369.76		7
    2	2019-02-18	795.15		8
    2	2019-02-19	715.65		9
    2	2019-02-21	537.71		10
    3	2019-02-08	12461.55	1
    3	2019-02-09	1052.99		2
    3	2019-02-10	85.69		3
    3	2019-02-12	769.85		4
    3	2019-02-13	943.86		5
    3	2019-02-14	276.81		6
    3	2019-02-15	369.76		7
    3	2019-02-16	369.76		8
    3	2019-02-18	795.15		9
    3	2019-02-19	715.65		10
    3	2019-02-21	537.71		11
    
  • 如果是在同一个连续登录的区间,用日期减去编号,那么结果都一样

    日期减少函数:data_sun(String_startdate,int_days)
    select tt1.id
           ,tt1.datestr
           ,tt1.sum_amount
           ,date_sub(tt1.datestr,rn) as grp
    from(
        select t1.id
           ,t1.datestr
           ,t1.sum_amount
           ,row_number() over(partition by id order by datestr) as rn
    from  (
         select  id
             ,datestr
             ,sum(amount) as sum_amount
     from deal_tb
     group by id,datestr
    ) t1
    ) tt1;
    //执行结果
    1	2019-02-08	12461.55	2019-02-07
    1	2019-02-09	1052.99		2019-02-07
    1	2019-02-10	85.69		2019-02-07
    1	2019-02-12	769.85		2019-02-08
    1	2019-02-13	943.86		2019-02-08
    1	2019-02-14	538.42		2019-02-08
    1	2019-02-15	369.76		2019-02-08
    1	2019-02-16	369.76		2019-02-08
    1	2019-02-18	795.15		2019-02-09
    1	2019-02-19	715.65		2019-02-09
    1	2019-02-21	537.71		2019-02-10
    2	2019-02-08	12461.55	2019-02-07
    2	2019-02-09	1052.99		2019-02-07
    2	2019-02-10	85.69		2019-02-07
    2	2019-02-12	769.85		2019-02-08
    2	2019-02-13	943.86		2019-02-08
    2	2019-02-14	943.18		2019-02-08
    2	2019-02-15	369.76		2019-02-08
    2	2019-02-18	795.15		2019-02-10
    2	2019-02-19	715.65		2019-02-10
    2	2019-02-21	537.71		2019-02-11
    3	2019-02-08	12461.55	2019-02-07
    3	2019-02-09	1052.99		2019-02-07
    3	2019-02-10	85.69		2019-02-07
    3	2019-02-12	769.85		2019-02-08
    3	2019-02-13	943.86		2019-02-08
    3	2019-02-14	276.81		2019-02-08
    3	2019-02-15	369.76		2019-02-08
    3	2019-02-16	369.76		2019-02-08
    3	2019-02-18	795.15		2019-02-09
    3	2019-02-19	715.65		2019-02-09
    3	2019-02-21	537.71		2019-02-10
    //由结果可以看出来,在连续登录区间日期相等
    
  • 根据上面已完成的数据,统计用户连续交易的总额、连续登陆天数、连续登陆开始和结束时间、间隔天数

    连续交易总额

    round(sum(ttt1.sum_amount),2) as sum_amount	//round()取两位小数
    

    连续登录天数

    count(ttt1.datestr) as days
    

    连续登录开始、结束时间

    min(ttt1.datestr) as start_date
    max(ttt1.datestr) as end_date
    

    间隔天数=下一条的开始时间—上一条的结束时间

    上一条的结束时间,需要用到窗口函数lag()
    lag(max(ttt1.datestr),1) over (partition by ttt1.id order by ttt1.grp)
    间隔天数,需要使用到日期函数datediff()
    datediff(min(ttt1.datestr),lag(max(ttt1.datestr),1) over (partition by ttt1.id order by ttt1.grp)) as interval_days
    

    最终代码

select ttt1.id
       ,ttt1.grp
       ,round(sum(ttt1.sum_amount),2) as sum_amount
       ,count(ttt1.datestr) as days
       ,min(ttt1.datestr) as start_date
       ,max(ttt1.datestr) as end_date
       ,datediff(min(ttt1.datestr),lag(max(ttt1.datestr),1) over (partition by ttt1.id order by ttt1.grp))
from(
    select tt1.id
       ,tt1.datestr
       ,tt1.sum_amount
       ,date_sub(tt1.datestr,rn) as grp
from(
    select t1.id
       ,t1.datestr
       ,t1.sum_amount
       ,row_number() over(partition by id order by datestr) as rn
from  (
     select  id
         ,datestr
         ,sum(amount) as sum_amount
 from deal_tb
 group by id,datestr
) t1
) tt1
) ttt1 group by ttt1.id,ttt1.grp
;
  • 最终结果
#  id   连续登录日期     连续交易总额           连续登录天数    开始时间         结束时间      间隔天数

    1	2019-02-07	13600.23		3	2019-02-08	2019-02-10	NULL
    1	2019-02-08	2991.65			5	2019-02-12	2019-02-16	2
    1	2019-02-09	1510.8			2	2019-02-18	2019-02-19	2
    1	2019-02-10	537.71			1	2019-02-21	2019-02-21	2
    2	2019-02-07	13600.23		3	2019-02-08	2019-02-10	NULL
    2	2019-02-08	3026.65			4	2019-02-12	2019-02-15	2
    2	2019-02-10	1510.8			2	2019-02-18	2019-02-19	3
    2	2019-02-11	537.71			1	2019-02-21	2019-02-21	2
    3	2019-02-07	13600.23		3	2019-02-08	2019-02-10	NULL
    3	2019-02-08	2730.04			5	2019-02-12	2019-02-16	2
    3	2019-02-09	1510.8			2	2019-02-18	2019-02-19	2
    3	2019-02-10	537.71			1	2019-02-21	2019-02-21	2

上一篇:(12)web安全|渗透测试|网络安全 信息收集,注入获取数据图解,附带靶场搭建教程及可能遇见的问题


下一篇:Pandas apply函数 计算日期相减