3,SQL专题训练之:连续登录天数,间隔一天也算一天(困难)

目录

一,原题链接

二,建表语句

三,分析

四,SQL解答

五,验证

六,知识点总结


一,原题链接

经典面试题,连续登录天数的升级版,间隔一天也算连续。求连续登录天数的用户id和用户等级,以及连续登录的次数,和连续登录的天数。

注意注意:期间间隔一天,也算连续  比如 7号,8号,10号,12号  。这算做连续登录4次,连续登录6天。

二,建表语句

 
 
drop table if exists author_tb;
CREATE TABLE author_tb
(
    author_id    int(10) NOT NULL,
    author_level int(10) NOT NULL,
    sex          char(10) NOT NULL
);
INSERT INTO author_tb
VALUES
    (101, 6, 'm'),
    (102, 1, 'f'),
    (103, 1, 'm'),
    (104, 3, 'm'),
    (105, 4, 'f'),
    (106, 2, 'f'),
    (107, 2, 'm'),
    (108, 5, 'f'),
    (109, 6, 'f'),
    (110, 5, 'm');
 
drop table if exists answer_tb;
CREATE TABLE answer_tb
(
    answer_date date     NOT NULL,
    author_id   int(10) NOT NULL,
    issue_id    char(10) NOT NULL,
    char_len    int(10) NOT NULL
);
 
INSERT INTO answer_tb
VALUES
    ('2021-11-1', 101, 'E001', 150),
    ('2021-11-2', 101, 'E002', 200),
    ('2021-11-3', 101, 'E002', 201),
    ('2021-11-5', 101, 'E002', 201),
    ('2021-11-1', 101, 'E002', 201),
    ('2021-11-1', 101, 'E002', 201),
    ('2021-11-1', 101, 'E002', 201),
    ('2021-11-1', 101, 'E002', 201),
    ('2021-11-1', 101, 'E002', 201),
    ('2021-11-1', 102, 'C003', 50),
    ('2021-11-1', 103, 'P001', 35),
    ('2021-11-1', 104, 'C003', 120),
    ('2021-11-1', 105, 'P001', 125),
    ('2021-11-1', 102, 'P002', 105),
    ('2021-11-2', 101, 'P001', 201),
    ('2021-11-3', 101, 'P002', 211),
    ('2021-11-2', 101, 'P001', 211),
        ('2021-11-2', 115, 'P001', 211),
        ('2021-11-4', 115, 'P001', 211),
         ('2021-11-6', 115, 'P001', 211),
          ('2021-11-8', 115, 'P001', 211),
          ('2021-11-7', 116, 'P001', 211),
          ('2021-11-8', 116, 'P001', 211),
          ('2021-11-9', 116, 'P001', 211),
          ('2021-11-12', 116, 'P001', 211),
    ('2021-11-2', 110, 'C003', 200),
    ('2021-11-2', 110, 'C001', 225),
    ('2021-11-2', 110, 'C002', 220),
    ('2021-11-3', 101, 'C002', 180),
    ('2021-11-4', 109, 'E003', 130),
    ('2021-11-4', 109, 'E001', 123),
    ('2021-11-5', 108, 'C001', 160),
    ('2021-11-5', 108, 'C002', 120),
    ('2021-11-5', 110, 'P001', 180),
    ('2021-11-5', 106, 'P002', 45),
    ('2021-11-5', 107, 'E003', 56),
    ('2021-11-6', 107, 'E003', 56),
        ('2021-11-7', 120, 'E003', 56),
        ('2021-11-8', 120, 'E003', 56),
        ('2021-11-10', 120, 'E003', 56),
        ('2021-11-14', 120, 'E003', 56),
        ('2021-11-12', 120, 'E003', 56);
 
 
select * from author_tb;
 
select * from answer_tb;


三,分析

分析表数据 我们得知答案:

120 连续登陆(期间中断1天也算一天) ,一共连续登陆了5次 7号, 8号, 10号 , 12号 ,14号 他的连续登陆天数是 7号到14号 一共是8天

116 连续登陆(期间中断1天也算一天), 一共连续登陆了 3次 7号,8号,9号 他的12号是不算的; 所以他的连续登陆天数是 3天

115 这个人 一共连续登陆了(期间中断1天也算一天) 一共连续登陆了 4次 2号,4号,

,6号,8号 他的连续登陆天数是 2号到8号 所以共计:7天

101 一共连续登陆了(期间中断1天也算一天) 一共连续登陆了 4次 分别是:

1号 2号 3号 5号 他的连续登陆天数是 1号到5号 共计: 5天

1,去重

2,排序取值

3,取相差值,得到相同的天数,则连续登录;得到连续的天数,则为间隔一天登录

4,再次对新列排序取值

5,再次取相差值,得到相同的天数,则为连续登录(包含间隔一天的登录)

6,记录连续登录的次数,记录不同用户的 连续登录2天之后的  最小天数,和最大天数

7,取到真实的登录天数  最大-最小 +1

8,分组,聚合,拿到连续的次数,连续的天数

9,拼接表,拿到最终数据


四,SQL解答

-- 连续登录3天 不足1天也算
with t1 as (
    #去重
    select distinct answer_date,author_id from  answer_tb
),
    # 排序 以id分组  以answer_date升序排序  取时间日期的排序编码
    t2 as (
        select  answer_date, author_id,
                row_number() over (partition by author_id order by answer_date) 用户的答复时间排序值
                from t1
    ),
    #取差值 为1的 算作连续登陆天数 即 日期减去日期的排序值得到的日期的列
    t3 as (
        select answer_date, author_id, 用户的答复时间排序值,
        date_add(answer_date,interval -用户的答复时间排序值 day ) 日期减去日期的排序值得到的日期
        from t2
    ),
    #在取差值 对  日期减去日期的排序值得到的日期  继续排序  用dense排序 允许并列
    t4 as (
        select answer_date, author_id, 用户的答复时间排序值, 日期减去日期的排序值得到的日期,
               dense_rank() over (partition by author_id order by 日期减去日期的排序值得到的日期) 排序2
            from t3
),
    #拿到连续 连续登陆的人
    t5 as (
        select answer_date, author_id, 用户的答复时间排序值, 日期减去日期的排序值得到的日期, 排序2,
               date_add(日期减去日期的排序值得到的日期,interval -排序2 day) 连续登陆天数2天

        from t4
    ),
#     在这个表里面 分组 统计天数   以id 分组  以相同天数次数聚合
    t6 as (
        select author_id,count(*) 不同id连续登陆2天的次数,
               max(answer_date) 最大日期,min(answer_date) 最小日期
        from t5 group by author_id,连续登陆天数2天
),# 根据连续登录人的人 取出 连续登陆3天的人
    t7 as (
    select author_id,不同id连续登陆2天的次数,
           timestampdiff(day,t6.最小日期,t6.最大日期)+1 as 连续天数   # 时间差 +1天 刚好是连续登陆的天数(间隔一天也算一天)
           from t6
),
    #拼接成最终的结果
    t8 as (
        select author_id,max(不同id连续登陆2天的次数) as 连续天数的次数,连续天数
        from t7
         group by author_id,连续天数 having max(不同id连续登陆2天的次数) >=3
    ),
    t9  as (
        select author_id,
               (select a.author_level from author_tb a where a.author_id in(t8.author_id) ) as author_level,
               连续天数的次数,
               连续天数
        from t8
    )
select * from t9;


五,验证

分析表数据 我们得知答案:

120 连续登陆(期间中断1天也算一天) ,一共连续登陆了5次 7号, 8号, 10号 , 12号 ,14号 他的连续登陆天数是 7号到14号 一共是8天

116 连续登陆(期间中断1天也算一天), 一共连续登陆了 3次 7号,8号,9号 他的12号是不算的; 所以他的连续登陆天数是 3天

115 这个人 一共连续登陆了(期间中断1天也算一天) 一共连续登陆了 4次 2号,4号,

,6号,8号 他的连续登陆天数是 2号到8号 所以共计:7天

101 一共连续登陆了(期间中断1天也算一天) 一共连续登陆了 4次 分别是:

1号 2号 3号 5号 他的连续登陆天数是 1号到5号 共计: 5天


六,知识点总结

知识点总结  连续登录天数 间隔一天也算连续  思路步骤:

第一步,去重;

第二步,排序取值。开窗,以id分组,以时间排序,拿到时间的排序值;

第三步  去差值,如果时间减去排序值  得到的天数是相同的 表示 连续登录;

        [比如第一条 是2024-10-1 他减去他的排序值1 2024-9-30

        第二条是  2024-10-2  他减去他的排序值2 2024-9-30     ]

        如果得到的天数是连续的 表示间隔1天登录;

第四步,再次排序取值。为求连续登录 哪怕间隔一天登录也连续,所以继续开窗  对新日期列排序;

第五步,再取差值。再取一个新的日期列,拿到 如果新日期列-新的排序列 得到是相同的 那么表示他们是连续登录的天(间隔一天也算一天);用dense_rank()  因为有相同的所以允许并列

第六步,实际上 我们统计相同的天数的次数 就是连续登录的次数。

                但是为了拿到我们连续登录的真实天数。所以需要记录下来 以id分组,

                连续登录2天的        相同日期 ,分组   取出该组:最小的天数  和最大的天数;

第七步,拿到真实的登录天数  最大日期和最小日期的时间差+1

第八步,去重  采用[分组,count聚合] 拿到 满足条件 大于3天 连续登录次数(间隔一天也算一天);

第九步,拼接表  以最终的是数据呈现给用户;  id ,等级,连续登陆的次数,连续登陆的天数 是个列

总结: 开窗函数的运用,取插值,用时间-排序的数值  如果是相等,则为连续登录天数

如果减去之后还是连续的天数,那么他们就是间隔1天连续登录的

 

  • 47
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值