HQL:用户连续登陆问题

HQL:用户连续登陆问题

问题:求一个用户连续登陆多少天,并且间隔一天也算连续。

数据:

id      login
id001	2021-01-01
id001	2021-01-02
id001	2021-01-03
id001	2021-01-05
id001	2021-01-07
id001	2021-01-08
id001	2021-01-15
id001	2021-01-16举例说明:id为id001的用户在1号至8号连续登陆8天。

建表语句:

create table tx (id string,login string
)
row format delimited fields terminated by '\t';

思路1 等差数列思想

1)给每条数据标记rank值:(这里的日期没有重复,因此使用Hive中的三种排序方式均可)

id001	2021-01-01	1
id001	2021-01-02	2
id001	2021-01-03	3
id001	2021-01-05	4
id001	2021-01-07	5
id001	2021-01-08	6
id001	2021-01-15	7
id001	2021-01-16	8

子查询:

select id,login,rank() over(partition by id order by login) rk
from tx; t1

2)使用login字段 - rank值:

id001	2021-01-00(举例,实际上应该为2020-12-31)
id001	2021-01-00
id001	2021-01-00
id001	2021-01-01
id001	2021-01-02
id001	2021-01-02
id001	2021-01-08
id001	2021-01-08

login字段 - rank值的结果相等代表连续

子查询:

selectid,date_sub(login,rk) flag
from t1; t2

3)根据上一步的结果分组,求count,count的结果代表严格连续的天数:

id001	2021-01-00	3
id001	2021-01-01	1
id001	2021-01-02	2
id001	2021-01-08	2

子查询:

select id,flag,count(*) ct
from t2
group by id,flag; t3

4)对结果集再进行rank:

id001	2021-01-00	3	1
id001	2021-01-01	1	2
id001	2021-01-02	2	3
id001	2021-01-08	2	4

子查询:

selectid,flag,ct,rank() over (partition by id order by flag) rk
from t3; t4

5)使用时间字段 - rank:

id001	2021-01- -1	3
id001	2021-01- -1	1
id001	2021-01- -1	2
id001	2021-01- 04	2

子查询:

select id,date_sub(flag,rk) flag,ct
from t4; t5

6)分组求连续天数,得到最终结果:

selectid,flag,count(*) ct
from t5
group by id,flag;

最终SQL:

select id,flag,sum(ct) + count(*) - 1 ct
from (select id,date_sub(flag, rk) flag,ctfrom (select id,flag,ct,rank() over (partition by id order by flag) rkfrom (select id,flag,count(*) ctfrom (select id,date_sub(login, rk) flagfrom (select id,login,rank() over (partition by id order by login) rkfrom tx) t1) t2group by id, flag) t3) t4) t5
group by id, flag;

思路2 直接分组思路

1)将上一行下移:

id001	2021-01-01	1970-01-01
id001	2021-01-02	2021-01-01
id001	2021-01-03	2021-01-02
id001	2021-01-05	2021-01-03
id001	2021-01-07	2021-01-05
id001	2021-01-08	2021-01-07
id001	2021-01-15	2021-01-08
id001	2021-01-16	2021-01-15

子查询:

selectid,login,lag(login,1,'1970-01-01') over (partition by id order by login) laglogin
from tx; t1

2)用当前日期减去上一行日期:

selectid,login,datediff(login,laglogin) flag
from t1; t2

3)给每一行做标记,上一步的结果大于2的标记为1,否则标记为0,然后sum求和

注意:这里使用spark引擎会报错,可以将引擎切换成MR,或者建表时login的字段类型改成date。

set hive.execution.engine=mr;
selectid,login,sum(if(flag > 2,1,0)) over (partition by order by login) groupsum
from t2; t3

4)按照id,groupsum分组,并且使用最大日期减去最小日期+1,就是最终结果

selectid,groupsum,datediff(max(login),min(login)) + 1
from t3
group by id,groupsum;

最终SQL:

select id,groupsum,datediff(max(login), min(login)) + 1
from (select id,login,sum(if(flag > 2, 1, 0)) over (partition by id order by login) groupsumfrom (select id,login,datediff(login, laglogin) flagfrom (select id,login,lag(login, 1, '1970-01-01') over (partition by id order by login) lagloginfrom tx) t1) t2) t3
group by id, groupsum;


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部