hiveSql 实现计算用户的最大连续登录天数 & 创建断连后的连续序号

本文详细介绍了如何使用HiveSQL进行用户行为分析,包括计算用户最大连续登录天数和创建浏览产品的连续序号。对于需求一,通过设置序号并计算日期差来找出连续登录天数;对于需求二,利用窗口函数和自连接技巧,实现了用户浏览产品线的连续序号,当产品线被中断后重新计数。这两种方法提供了灵活的数据分析解决方案。
摘要由CSDN通过智能技术生成

1.需求一:

计算每个用户在一段时间内的最大连续登录天数

1.1.已有数据

usernamelogintime
A2021-10-01
A2021-10-02
A2021-10-03
A2021-10-05
A2021-10-06
A2021-10-09
B2021-10-01
B2021-10-02
B2021-10-03
B2021-10-04

1.2.期望结果

usernamemax_login_days
A3
B4

1.3.分析

1.连续登陆,就是在连续登陆的期间内,后一天和前一天的差值为1,不能为大于1的值,直到间断。可以设置一列序号,如果是连续的话,这列序号也是会随着日期同步增长的,那么日期减去这个序号,应该都是一个确定的日期。

1.4.实现

select
    username,max(max_login_days) as max_login_days
from
    (select
        username,diff_day,count(1) as max_login_days
    from
        (select
            username,login_time
            ,substr(DATEADD(to_date(login_time,'yyyy-mm-dd'),-irank,'dd'),1,10) as diff_day -- 将用户的登录日期与排序序号做差计算一个日期
        from
            (select
                username,login_time
                ,ROW_NUMBER() OVER(PARTITION BY username ORDER BY login_time) AS irank 
            from tb_user_login
            ) t1
        ) t2
    group by username,diff_day
    ) t3
group by username;

2.需求二

用户浏览产品线连续排序序号,若中间插入其他产品线再出现原产品线则从1开始再计数

2.1.已有数据

typehourusername
ask9liu
ask10liu
blog11liu
d12liu
d13liu
d14liu
ask15liu
d16liu

2.2.期望结果

typehourusernameirank
ask9liu1
ask10liu2
blog11liu1
d12liu1
d13liu2
d14liu3
ask15liu1
d16liu1

2.3.分析

这里只想了仅一个用户情况,可以看到期望结果中该用户在9点到16点分别浏览了多个产品线,按照浏览时间排序连续产品线的序号期望是连续的,被别的产品线打断后再出现则再次从1开始计数。逆向思维想,如果能完成上述排序,则在按照hour排序的前提下,相邻的相同的产品线type能有个相同的值。如果有这样的一个列irank_tmp,再将type和该列一起row_number开窗即可。
例如:

typehourusernameirank_tmp
ask9liu0
ask10liu0
blog11liu1
d12liu2
d13liu2
d14liu2
ask15liu3
d16liu4

2.4.实现方式一

with tmp as (
select 
'ask'as type,9 as pt ,'liu'as user 
union all 
select 
'ask'as type,10 as pt ,'liu'as user 
union all 
select 
'blog'as type,11 as pt ,'liu'as user 
union all 
select 
'd'as type,12 as pt ,'liu'as user 
union all 
select 
'd'as type,13 as pt ,'liu'as user 
union all 
select 
'd'as type,14 as pt ,'liu'as user 
union all 
select 
'ask'as type,15 as pt ,'liu'as user 
union all 
select 
'd'as type,16 as pt ,'liu'as user 
)
,
tmp1 as 
(
    select
        type,pt,user
        ,ROW_NUMBER() OVER(PARTITION BY user ORDER BY pt) AS irank 
    from tmp
)
select
    type,pt,user,irank,
    ROW_NUMBER() OVER(PARTITION BY type,flag ORDER BY flag) AS con_rank 
from(
    select
        a.type,a.pt,a.user,a.irank, case when a.irank is not null and b.irank is null and c.irank is null then a.irank else 0 end as flag
    from tmp1 a
    left join tmp1 b
    on a.irank = b.irank + 1 and a.type = b.type
    left join tmp1 c
    on a.irank = c.irank - 1 and a.type = c.type
) t;

方式一的做法比较麻烦,思路是将数据按照用户的浏览时间排序后记录序号,错位自连接两次,一次往上错位,一次往下错位。用前三行示例:

  1. 按照时间排序后是
typehourusernameirank_tmp
ask9liu1
ask10liu2
blog11liu3
  1. 错位两次后
typehourusernamea.irank_tmpb.irank1c.irank2
ask9liu1\N2
ask10liu21\N
blog11liu3\N\N
  1. 分析错位数据
    只有是没有连续产品线的数据的b.irank1 和 c.irank2是空值,a.irank_tmp不为空。此时只用将这种情况的数赋为原来的时间排序的序号即irank_tmp,其他都为0即可。可得到:
typehourusernameirank_tmpirank
ask9liu10
ask10liu20
blog11liu33
d12liu40
d13liu50
d14liu60
ask15liu77
d16liu88
  1. 此时只要按照type和irank分组做开窗row_number即可获得预期数据形式

2.5.实现方式二

with tmp as (
select 
'ask'as type,9 as pt ,'liu'as user 
union all 
select 
'ask'as type,10 as pt ,'liu'as user 
union all 
select 
'blog'as type,11 as pt ,'liu'as user 
union all 
select 
'd'as type,12 as pt ,'liu'as user 
union all 
select 
'd'as type,13 as pt ,'liu'as user 
union all 
select 
'd'as type,14 as pt ,'liu'as user 
union all 
select 
'ask'as type,15 as pt ,'liu'as user 
union all 
select 
'd'as type,16 as pt ,'liu'as user 
)
,
tmp1 as 
(
    select
        type,pt,user
        ,ROW_NUMBER() OVER(PARTITION BY user ORDER BY pt) AS irank 
    from tmp
)
select
    type,pt,user,
    ROW_NUMBER() OVER(PARTITION BY type,irank1-irank2 ORDER BY irank1-irank2) AS irank 
from(
    select
        type,pt,user
        ,ROW_NUMBER() OVER(PARTITION BY user ORDER BY pt) AS irank1
        ,ROW_NUMBER() OVER(PARTITION BY user,type ORDER BY pt) AS irank2
    from tmp
    ) t;

方式二的做法比较灵巧,思路是将数据按照用户的浏览时间排序后记录序号,再将数据按照type和时间做升序排序记录序号,再将这两个序号做差,即可得到步骤1.3分析中的irank_tmp。示例:

typehourusernameirank_ptirank_typeirank_pt - irank_type
ask9liu110
ask10liu220
blog11liu312
d12liu413
d13liu523
d14liu633
ask15liu734
d16liu844

此时还是将type与这个差值分组做row_number即可得到期望结果

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@nanami

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值