面试题 Hive-SQL查询连续活跃登录用户思路详解_sql查询连续登录两天的用户

54 阅读4分钟

img img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

dt string, user_id string, age int) ROW format delimited fields terminated BY ',';

INSERT INTO TABLE test5active VALUES ('2019-02-11','user_1',23),('2019-02-12','user_1',23),('2019-02-11','user_2',19), ('2019-02-11','user_3',39),('2019-02-11','user_1',23), ('2019-02-11','user_3',39),('2019-02-11','user_1',23), ('2019-02-12','user_2',19),('2019-02-13','user_1',23), ('2019-02-15','user_2',19),('2019-02-16','user_2',19);


### 登录日志去重


因为每天用户登录次数可能不止一次,所以需要先将用户每天的登录日期去重。



select distinct user_id,dt from test5active


![在这里插入图片描述](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/9e6bcdf377254920aa9e46332789cf82~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzM5MTQ5MjgwNjA=:q75.awebp?rk3s=f64ab15b&x-expires=1771316219&x-signature=9Jtwl5OW2091okW1gX9NE7rsTJw%3D)


## 一、思路一


1、再用row\_number() over(partition by \_ order by \_)函数将用户id分组,按照登陆时间进行排序。


2、计算登录日期减去第二步骤得到的结果值,用户连续登陆情况下,每次相减的结果都相同。


3、按照id和日期分组并求和,筛选大于等于2的即为连续活跃登陆的用户。


### 1.1、分组排序



SELECT t1.user_id, t1.dt, ROW_NUMBER() OVER(PARTITION BY t1.user_id ORDER BY t1.dt) day_rank FROM ( SELECT DISTINCT dt,user_id FROM test5active )t1;


![在这里插入图片描述](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/87dfca7b257545ce8bfe184c9046ea41~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzM5MTQ5MjgwNjA=:q75.awebp?rk3s=f64ab15b&x-expires=1771316219&x-signature=YBfbiXVvEwW4ebwTeDaWe3mCwWw%3D)


### 1.2、日期减去计数值得到结果, 用户连续登陆情况下,每次相减的结果都相同



SELECT t2.user_id, t2.dt, date_sub(t2.dt, t2.day_rank) AS dis FROM ( SELECT t1.user_id, t1.dt, ROW_NUMBER() OVER(PARTITION BY t1.user_id ORDER BY t1.dt) day_rank FROM (SELECT DISTINCT dt, user_id FROM test5active) t1 )t2;


![在这里插入图片描述](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/149a7f48ff9249cfb901b1f1ac0a4f73~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzM5MTQ5MjgwNjA=:q75.awebp?rk3s=f64ab15b&x-expires=1771316219&x-signature=6OgetiLd%2B8Hwdl%2BUJAyPd3ru2cI%3D)


### 1.3、根据 user\_id 和 dis 分组,得到用户的 开始、结束时间、连续登录天数



SELECT t3.user_id, MIN(t3.dt), MAX(t3.dt), COUNT(1) FROM (SELECT t2.user_id, t2.dt, DATE_SUB(t2.dt, t2.day_rank) AS dis FROM (SELECT t1.user_id, t1.dt, ROW_NUMBER() OVER(PARTITION BY t1.user_id ORDER BY t1.dt) day_rank FROM (SELECT DISTINCT dt, user_id FROM test5active) t1 ) t2 ) t3 GROUP BY t3.user_id,t3.dis


![在这里插入图片描述](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/8891489265e4466388d421921e2d2143~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzM5MTQ5MjgwNjA=:q75.awebp?rk3s=f64ab15b&x-expires=1771316219&x-signature=%2B%2FtTc8yTtVociKJ1IYJ%2FPbGeUPE%3D)


### 1.4、连续登录超过两天用户



-- 1.3基础上 HAVING COUNT(1) > 1;


![在这里插入图片描述](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/391078a2faa245efbd9eb3a980bdae14~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzM5MTQ5MjgwNjA=:q75.awebp?rk3s=f64ab15b&x-expires=1771316219&x-signature=uGQ04iqS9IVY999iJvJlTppuNkU%3D)  
 接下来就是用户去重


## 二、思路二: 使用 LAG(向后)或者 LEAD(向前)


`LEAD(col, n, default) OVER()`


* 说明: 用于统计窗口内向下第n行的值
* 参数1: 为要取值的列名
* 参数2: 为向下第n行,默认值为1,这个值是固定的,不能动态的变化
* 参数3: 为默认值,当向下第n行的值为NULL时,取默认值,如果不指定,则默认值为NULL



SELECT user_id, t1.dt, LEAD(t1.dt) OVER(PARTITION BY user_id ORDER BY t1.dt) AS last_date_id FROM (SELECT DISTINCT dt, user_id FROM test5active) t1;

img img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!