HQL:连续签到_三种解决方案

文章介绍了在HQL中处理连续签到问题的三种策略:等差法、累加求和法和填充法。每种方法都涉及到了date_sub、datediff、last_value()over()、lag()over()等日期处理和窗口函数的使用,通过对用户签到数据的分析和处理,计算出用户的连续签到天数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HQL:连续签到_三种解决方案

表结构

/*
table_name : user_log
fields:
1.uid
2.artical_id 视频id
3.in_time 进入时间
4.out_time 离开时间
5.sign_in 是否签到

几条表数据

在这里插入图片描述

考察到的知识点

  1. date_sub()

  2. datediff()

  3. last_value(field,true/false) over()

  4. lag(field) over()

  5. sum(),count()

  6. 对于开窗函数的界限问题

    /*
    1.不指定partition by  默认全表
    2.不指定order by 默认全表,可用于sum()场景
    3.不使用窗口句子
    	1.不适用order by 默认全表
    	2.使用order  by,默认第一行到当前行
    

思路

第一步肯定是先找出所有签到的数据

等差法

然后我们以用户分组,in_time排序,然后进行排序,如果连续,那么in_time - 排序的值必定得到一个相等的值,然后我们再根据 差值+uid 分组即可得到连续的值

累加求和法

可以先获取每条数据上一条数据的in_time值,然后相减,等差1则置为0,否则置为1,然后我们在通过一个开窗函数进行累加 最后再通过 uid+累加值分组即可

填充法

填充法也是要先获取上一条记录然后做差,相同为null,因为第一天签到无法获取上一天,那么我们可以特殊处理,如果为null的话,值设置为in_time 然后通过last_value() over() 填充,

方案一:等差法

/*
select
	uid,
	flag,
	count(1)
from(
    select
        uid,
        date_format(in_time,'yyyy-MM-dd'),
        date_sub(date_format(in_time,'yyyy-MM-dd'),rank() over(partition by uid,order by in_time asc)) flag
    from user_log
    where sign_in=1
)t 
group by uid,flag

方案2 累加求和法

/*
select
	uid,
	mark,
	count(1)
from(
    select
        uid,
        sum(ck) over(partition by uid order by in_time) mark
    from(
        select
            uid,
            in_time,
            if(in_time = null ,1,if(datediff(in_time,flag)=1,0,1)) ck
        from(
            select
                uid,
                date_format(in_time,'yyyy-MM-dd') in_time,
                lag(date_format(in_time,'yyyy-MM-dd')) over(partition by uid,order by in_time asc)flag
            from user_log
            where sign_in=1
        )t
    )t2
)t3
group by uid,mark

方案三 填充法

select
	uid,
	mark,
	count(1)
from(
    select
        uid,
        last_value(ck,true) over(partition by uid,order by in_time) mark
    from(
        select
            uid,
            in_time,
            if(in_time = null ,in_time,if(datediff(in_time,flag)=1,null,in_time)) ck
        from(
            select
                uid,
                date_format(in_time,'yyyy-MM-dd') in_time,
                lag(date_format(in_time,'yyyy-MM-dd')) over(partition by uid,order by in_time asc)flag
            from user_log
            where sign_in=1
        )t
    )t2
)t3
group by uid,mark
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

C_x_330

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

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

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

打赏作者

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

抵扣说明:

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

余额充值