需求
每个用户连续登录最大天数
建表语句
create table login(
id string,
rq string
)
row format delimited fields terminated by '\t'
;
数据
#这里将数据分开,便于直观看到连续登录天数
insert into table login values
(1,"2019-07-26"),
(1,"2019-07-27"),
(1,"2019-07-30"),
(1,"2019-07-31"),
(1,"2019-08-01"),
(2,"2019-07-26"),
(2,"2019-07-27"),
(2,"2019-07-28"),
(2,"2019-07-30"),
(2,"2019-07-31");
实现
select
t3.id,
max(t3.num)
from
(select
t2.id,
count(*) as num
from
(select
t1.id,
date_sub(t1.rq,t1.n) as rq1
from
(select
id,
rq,
row_number() over(partition by id order by rq) as n
from
login
group by id,rq -- 第一次分组
)t1
)t2
group by t2.id,t2.rq1 -- 第二次分组
)t3
group by t3.id -- 第三次分组
;
结果
Total MapReduce CPU Time Spent: 7 seconds 320 msec
OK
t3.id _c1
1 3
2 3
Time taken: 38.097 seconds, Fetched: 2 row(s)
分析
1、通过对需求理解发现,首先需要对用户id开窗
2、连续登录,所以时间信息,并按照升序,需要在窗口里面添加order by
3、核心逻辑——连续登录的判断是,通过排序添加序号,再用当前日期和当前序号做差,
如果得到日期相同,则表示是连续日期,所以使用row_number,
4、整体的逻辑顺序是先排序添加序号字段、计算差值日期、统计差值日期相同数量、最后得出每个用户差值日期数最多即需求
扩展
1、这里t1,t2可以合并为一步,减少一次子查询
2、第一次分组是每个用户每天只有一条数据,第二次分组是统计差值日期相同数量,第三次分组是统计每个用户最大连续登录天数
知识点
1、row_number添加序号,无论字段值是否相同
2、date_sub(日期,数值),用日期-数值,即当前日期的前n天,返回值是日期字符串类型
分析中第3点在hive sql系列(三)中计算连续日活中也用到了日期差值,参考链接: