0
点赞
收藏
分享

微信扫一扫

SQL常见面试提:解决连续问题(CSDN签到领金币、连续登录天数等问题)

MaxWen 2022-05-03 阅读 27

SQL解决连续问题(连续登录天数等问题)

目录内容


连续登录天数问题我们可以看作是一个排队的问题,就是把连续登录的一组当作是一个队伍,这个队伍有着共同的领队,如果中断,则去往另一个队伍,这个队伍也有一个同样的领队

一、问题描述

怎么理解呢?看个栗子:

比如一组数据

2022-04-13
2022-04-14
2022-04-15
2022-04-16
2022-04-17
2022-04-19
2022-04-20
2022-04-22

把连续的天数当做是一个队伍,那么就会有下面的数据

队伍1:
领队: 2022-04-12
2022-04-13
2022-04-14
2022-04-15
2022-04-16
2022-04-17
队伍2:
领队: 2022-04-18
2022-04-19
2022-04-20
队伍3:
领队: 2022-04-21
2022-04-22

就像上述的样式,为什么领队是前一天呢,其实我们可以看到,每个队伍按照顺序排序,刚好领队就是这个日期的前n天,n就是排序序号,比如:队伍1中,2022-04-13排序是1,领队就是前一天2022-04-12

二、小试牛刀

小需求:找到连续登录天数最长是几天

拿一个队伍举例:

步骤1:按照日期排序

日期			序号			领头
2022-04-13		1		2022-04-12
2022-04-14		2		2022-04-12
2022-04-15		3		2022-04-12
2022-04-16		4		2022-04-12
2022-04-17		5		2022-04-12
2022-04-19		6		2022-04-13
2022-04-20		7		2022-04-13

步骤2:按照零头进行分组,再次排序(其实这里不用排序,直接得到队伍个数,哪个最大就行)

日期			序号			领头		二次排序
2022-04-13		1		2022-04-12		1
2022-04-14		2		2022-04-12		2
2022-04-15		3		2022-04-12		3	
2022-04-16		4		2022-04-12		4	
2022-04-17		5		2022-04-12		5
2022-04-19		6		2022-04-13		1
2022-04-20		7		2022-04-13		2

代码:

select count(*) max_date
from (
select date_sub(date_log, dr) top_date
  ,date_log
from (
select date_log
  ,dense_rank()
  over(order by date_log) dr  -- 第一次排序
from tbl_log
) t1
) t2
group by top_date
order by count(*) desc
limit 1;

在这里插入图片描述

三、问题升级

如果涉及的问题不只是作为求得连续登录的最大值,变成了连续天数不一样做出的判断也不一样,比如,CSN之前的签到,连续签到的天数不一样,给的金币也不一样,而且按照一周一个轮询 ,就算你中间断了,在周三开始再次签到,也会按照第一天,该怎么办

日期			序号		第几天
2022-04-13		1		1
2022-04-14		2		2
2022-04-15		3		3
2022-04-16		4		4
2022-04-17		5		5
2022-04-19		6		1
2022-04-20		7		2

就像上面的描述

其实也很简单,就是比着最大登录天数增加了一个步骤,按照领头在做一次排序

日期			序号			领头		二次排序
2022-04-13		1		2022-04-12		1
2022-04-14		2		2022-04-12		2
2022-04-15		3		2022-04-12		3	
2022-04-16		4		2022-04-12		4	
2022-04-17		5		2022-04-12		5
2022-04-19		6		2022-04-13		1
2022-04-20		7		2022-04-13		2

第二次排序就是一个周期内的第几次签到

代码:

select date_log
  ,top_date
  ,dense_rank()
  over(partition by t2.top_date order by date_log) trk
from (
select distinct date_sub(date_log, dr) top_date
  ,date_log
from (
select date_log
  ,dense_rank()
  over(order by date_log) dr  -- 第一次排序
from tbl_log
) t1
) t2;

在这里插入图片描述

那么如果是第一天就是1分钱,第二天也是1分钱,第三天给2分钱,第四天给3分钱,第五天给5分钱,第六天给8分钱,第七天给1毛3,然后轮询

这个实现其实就是按照第二次排序的给的,使用一个取余即可

select date_log
  ,top_date
  ,dense_rank()
  over(partition by t2.top_date order by date_log) trk
  ,case dense_rank() over(partition by t2.top_date order by date_log) % 7
    when 1 then 1
    when 2 then 1
    when 3 then 2
    when 4 then 3
    when 5 then 5
    when 6 then 8
    when 0 then 13
    else 0
  end coin
from (
select distinct date_sub(date_log, dr) top_date
  ,date_log
from (
select date_log
  ,dense_rank()
  over(order by date_log) dr  -- 第一次排序
from tbl_log
) t1
) t2;

在这里插入图片描述
注:当然拉,这里知识举个栗子,真实的签到活动中要比这个逻辑复杂,这里当作是一个思维扩展即可

举报

相关推荐

0 条评论