SQL面试题每日一题之求解用户最长连续登录天数

SQL面试题每日一题之求解用户最长连续登录天数

之后会不定期更新每日一题sql系列。

SQL面试题每日一题系列内容均来自于网络以及实际使用情况收集,如与各大厂面试题有雷同,纯属巧合。

1.题目

问题:以下为多个用户每日登录记录数据,求解每个用户最长连续登录天数。

该问题为此还会衍生出,标记处连续登录n天用户。用户连续登录中出现的所有未登录日期等。具体之后进行分析计算演示,欢迎持续关注。

2.基础数据准备

create table if not exists temp.user_login_log (
  `id` bigint comment '用户id',
  `login_date` string comment '登录日期'
) comment '用户每日登录流水'

数据预览

idlogin_date
12024-04-25
12024-04-26
12024-04-27
12024-04-28
12024-04-30
12024-05-01
12024-05-02
12024-05-04
12024-05-05
12024-05-06
12024-05-07
22024-04-25
22024-04-28
22024-05-01
22024-05-03
22024-05-04

3.问题分析

求解每个用户最长连续登录天数,考察的是对日期加减函数的使用以及对排序开窗函数的应用。排序开窗函数详见SQL窗口分析函数使用详解系列二之分组排序窗口函数

维度评分
题目难度⭐️⭐️⭐️⭐️
题目清晰度⭐️⭐️⭐️⭐️
业务常见度⭐️⭐️⭐️⭐️⭐️

4.解题SQL

1.对原始数据排序生成序号

这步很重要,作为判断是否连续的基础数据处理。

select id,login_date
	,row_number() over(partition by id order by login_date) as rank_id 
from temp.user_login_log
order by id,login_date

数据结果

idlogin_daterank_id
12024-04-251
12024-04-262
12024-04-273
12024-04-284
12024-04-305
12024-05-016
12024-05-027
12024-05-048
12024-05-059
12024-05-0610
12024-05-0711
22024-04-251
22024-04-282
22024-05-013
22024-05-034
22024-05-045

可以看到这里是按用户id分组,按日期进行了一个分别排序。

2.对排序进行做差值

因为如果是连续登录,那登录日期减去自增的排序就会始终是一个日期值。比如3号登录排序1,4号登录排序2,5号登录排序3。则他们之间的差值都是2。这就是连续。反之,如果差值不一致,就是不连续。

select id,login_date,date_sub(login_date,rank_id) as date_gap 
from (
	select id,login_date
  	,row_number() over(partition by id order by login_date) as rank_id 
  from temp.user_login_log
) a
order by id,login_date

数据结果

idlogin_datedate_gap
12024-04-252024-04-24
12024-04-262024-04-24
12024-04-272024-04-24
12024-04-282024-04-24
12024-04-302024-04-25
12024-05-012024-04-25
12024-05-022024-04-25
12024-05-042024-04-26
12024-05-052024-04-26
12024-05-062024-04-26
12024-05-072024-04-26
22024-04-252024-04-24
22024-04-282024-04-26
22024-05-012024-04-28
22024-05-032024-04-29
22024-05-042024-04-29

可以看到连续登录的日期的记录其求解的date_gap是相同的,这时候大多人都能反应过来,求解最长连续登录天数,接下来只要按date_gap分组计数,然后求个最大值就可以了。

3.按date_gap分组计数

select id,date_gap,count(0) as login_day from (
    select id,login_date,date_sub(login_date,rank_id) as date_gap from (
        select id,login_date
            ,row_number() over(partition by id order by login_date) as rank_id 
        from temp.user_login_log
    ) a
) b 
group by id,date_gap
order by id,date_gap

数据结果

iddate_gaplogin_day
12024-04-244
12024-04-253
12024-04-264
22024-04-241
22024-04-261
22024-04-281
22024-04-292

连续登录天数login_day 一目了然了。

4.分组求最长连续登录天数

select id,max(login_day) as max_login_day from (
  select id,date_gap,count(0) as login_day from (
    select id,login_date,date_sub(login_date,rank_id) as date_gap from (
      select id,login_date
      ,row_number() over(partition by id order by login_date) as rank_id 
      from temp.user_login_log
    ) a
  ) b 
  group by id,date_gap
) c
group by id
order by id

数据结果

idmax_login_day
14
22

用户1最长登录天数为4天,用户2最长登录天数为2天。

5.衍生问题解答

如果求解的不是最长连续登录天数,而是连续登录n天的所有记录呢?

可以考虑用lead()函数尝试求解。

下期进行完整解答。

以上,本期全部内容。

感谢阅读。

按例,欢迎点击此处关注我的个人公众号,交流更多知识。

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鲁边

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值