sql 连续三天登陆_连续登录的那些事

本文详细介绍了如何使用SQL解决连续登录的问题,包括利用窗口函数处理连续天数、求解连续三天登录用户及连续三个月登录用户的方法。通过具体实例和代码演示,展示了从计算连续登录天数到找出特定连续登录周期用户的过程。

   SQL连续登录这个问题在实际工作中遇到的情况比较多,结合窗口函数的使用会使SQL代码简洁易懂,下面我把最近刷题过程中遇到的连续登录这一类问题做一个总结。

首先解决SQL连续登录这一类问题核心的思路如下图所示

0dcff6dbd7afa76cbf63af07f3a39d15.png

  假设用户是连续登陆的情况下,那么用登陆日期减去排名后的日期应该是一样的,连续登录的用户的日期是一个差值为1的等差数列。

下面的题用到的数据为,数据库为Mysql8.0以上的版本

insert into visitlog values('2020-01-02 09:30:05','pc',246731); insert into visitlog values('2020-01-03 09:30:05','pc',246731); insert into visitlog values('2020-02-01 09:30:05','pc',246731); insert into visitlog values('2020-02-02 09:30:05','pc',246731); insert into visitlog values('2020-04-01 09:30:05','pc',246731);insert into visitlog values('2019-12-01 09:30:05','pc',243186); insert into visitlog values('2020-01-01 09:30:05','pc',243186); insert into visitlog values('2020-02-01 09:30:05','pc',243186); insert into visitlog values('2020-02-02 09:30:05','pc',243186);insert into visitlog values('2019-11-01 09:30:05','pc',286325); insert into visitlog values('2019-12-01 09:30:05','pc',286325); insert into visitlog values('2020-01-01 09:30:05','pc',286325); insert into visitlog values('2020-02-01 09:30:05','pc',286325);insert into visitlog values('2020-01-01 09:30:05','pc',321678); insert into visitlog values('2020-01-02 09:30:05','pc',321678); insert into visit_log values('2020-01-03 09:30:05','pc',321678); insert into visitlog values('2020-01-04 09:30:05','pc',321678); insert into visitlog values('2020-01-05 09:30:05','pc',321678);

建表语句为

create table visitlog( logtime datetime not null ,terminal char(10) not null ,uid int not null )

Q1 求每一位用户的最早登陆日、最近登陆日、最大的连续登录天数

1求出每位用户的连续登录天数(第一题会把每一个分解步骤写清楚,便于理解)

  首先用Row_number函数对日期进行排序,最后用DATE_SUB函数计算logtime减去排名之后的日期,从这里可以看出只要是连续登录的用户fuzhulie这一列的日期都是一样的。

7d1a25eb3dda62ce315e35fc1821ab23.png

运行的结果为

3e02fb6e7b76834a6c80c30b92b21665.png

2 以uid和fuzhulie作为分组依据,只要是连续登录的用户都会被分到一组里,在每一组里最小的日期就是用户的最早登录日期,最大的日期就是用户的最近登陆日期。

运行的代码为

20e43381783aae9d451e923cac03a569.png

运行的结果为

83404bf99f1ed6a87822a6f27e53302a.png

从上图可以看出每一个用户的登录日期和登录次数,

3 求每一个用户的最大登录次数时,只需要在最外面做一层嵌套,MAX(登录次数)即可

 (下面的这个代码没有考虑性能问题,只是为了说明白这个道理)

运行的代码为

ce7143024653c9750ff7e947438925bc.png

运行的结果为

4a54edda6fdcc96fb044035a3fa32e02.png

Q2:求解连续登录三天的用户都有哪些(其实用上面的方法可以直接求登陆三天的用户有哪些,只需要加一个where = 3作为限制条件即可)

1 这次用LEAD函数进行操作,对logtime进行向下偏移,偏移后的日期列命名为第三天登陆日期

运行的代码为

ada88a7b96301a597e2f78157e7a07d1.png

运行的结果为

c70a1505153d07f67932d648f81869df.png

  为什么lead()函数中偏移参数设为2吗?假设他三天连续登录,那么两个日期之间相差的行数为2,当lead( )进行偏移时是不包括它本身这一行的。

2 用date计算出第三次登录日期跟logtime的差值然后再加上1是否等于3,等于3证明该用户是连续登录三天的,为空值或者最后的结果都不是3,就说明用户不是连续三天登录的。

运行的代码为

939ee65fa3732a635b0d9528618ada0e.png

运行的结果为

7eb23e79b93422f6f006326a69c49a26.png

Q3 求连续三个月都连续登录的用户(注意是三个月,不是三天了)

在这里需要有一个相对的概念,就是我们需要以谁为基准去进行月份的偏移。如果是1-12月则取month的整数值进行计算即可,不过涉及到跨年就会麻烦一点所以要将yyyy-mm格式转化成连续的整数,以首单的第一个月的年份为基准,某个用户下单月份为201811,201812,201901,201902
其中基准(最小年份)是2018年,进行转化,则有:
201811 -> (2018-2018)\*12+11 = 11
201812 -> (2018-2018)\*12+12 = 12
201901 -> (2019-2018)\*12+1 = 13
201902 -> (2019-2018)\*12+2 = 14
然后再参照**Q1**的思路,对齐基准偏移然后计数。
根据上面的思路,查询到数据中最小的登陆日期为2019年11月

1 第一步,首先对月份进行提取,把月份变成一个相对的月份。运行的代码为

7a0ce7a193eca1b0bb290ac49d708101.png

2 然后根据Q2的方法求出连续3个月登录的用户(用Q1的方法也可以)

adf5435f5cf2aab3004653d9d79330b0.png

运行的结果为

36c5ac2c9cd594d5c10c460de037da05.png

总结, Q1和Q2的代码有些啰嗦,只是为了把每一步展示清楚。如date_sub( )函数对日期进行加减时,如下图操作代码就会简洁不少。

07e3925f25ac705f1c5a80d270b9bf6b.png

拓展 试想一下怎样求解连续3 周登录的用户呢

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值