连续登陆N天问题的通用解决方案
文章目录
一、问题描述
- 表结构:
有一张用户登陆记录表,结构与参考数据如下图
- 查询:
最近一月内,连续登陆超过5天的用户
- 条件1:
每个用户,每天可以有0条或多条登陆记录
- 条件2:
最近一个月(或者最近30)内,任意时间段,连续登陆5天都可以; 不一定是最后5天,中间时段也可以;
二、数据准备
表结构如下图,也可直接下载文章附加的SQL脚本文件,生成数据表结构等,方便使用。
三、通用方案一:使用 ROW_NUMBER() 窗口函数
-
数据去重
每用户一天最多保留一条记录,并把时间转换为日期方便后续操作
-
排名
使用row_number() over(partition by 用户id order by 登录日期) 进行排名
-
判断是否连续
在第二步的基础上,登陆时间 - 排名后(使用date_sub()函数),得到的结果是同一天,则说明是连续的;否则是不连续的。这里的排名,是个等差数列。例如:2024-08-01减去它对应的排序数1,就是2024-07-31;2024-08-02减去它对应的排序数字2,就是2024-08-01;2024-08-03减去它对应的排序数字3,就是2024-08-02;到目前为止该用户已经连续登录三天了。就是这个逻辑,我们可以使用 date_sub() 函数。
-
获取结果
对上一步的结果,分组聚合后过滤,得到想要的数据说明:如果需求是求出所有登陆中,任意连续的N天记录,则要删除之前步骤中的where子句;如果是最后n天的情况下,再加上过滤,减少原始数据量,提高性能。
通用方案二:使用 LEAD() 窗口函数
大思路一样,只是和下面的行比较。不始上面的思路清楚。有很多步,是相同的,就不再一一做了。
感兴趣的友友们,可以试试。记得来这里炫一炫噢!
总结
水平、时间有限,不中之处,请条友们不吝赐教!