• sql解决连续登录问题变形-节假日过滤


    一、说明

    先说需要实现的效果,就是判断节假日和工作日,如果是工作日,返回当日,如果是节假日或者休息,返回一下次工作的日期
    06-01 工作日 06-01
    06-02 双休日 06-04 *因为 下一个工作日是06-04
    06-03 双休日 06-04
    06-07、06-08、06-09节假日, 返回06-10, 即下一个工作日

    连续登录天数之前讲解过有两种解法,可以解决连续登录问题,那么在实际生产中也是经常使用到,但是对于一些此类问题的变形,是否能够轻松解决?

    二、需求说明

    最近接到一个需求,也不算是需求,是一个小的功能实现。之前一直再做事件告警的需求,需要对告警事件进行反馈,判断是否是当日反馈。
    最开始实现时候想法很简单,只考虑到了双休日,就设定如果是双休日的告警事件,在周一时候反馈就认为是当日反馈,当时是这么实现的:
    如果是周六,反馈日期增加2,如果是周日,反馈日期增加1

    case dayofweek(alarm_date)
    	when 7 then date_add(fb_date,2)
    	when 0 then date_add(fb_date,1)
    else fb_date end as fb_date
    
    • 1
    • 2
    • 3
    • 4

    但是在实际使用中,发现了存在节假日的卡点,尤其是上半年的节假日比较多,所以不过滤节假日对结果有很大的影响,另外,对于一些双休日,也可能是工作日串休。

    三、过滤节假日

    为什么会说这个问题是连续登录问题的变形呢?我们想一想,节假日是不是连续的?无论是双休还是节假日,都是连续的日期。那么这个问题就变成了,我们要分辨出哪些是节假日?哪些是工作日?
    这种实现的思路我想到的有两个

    思路一

    编写UDF,在jar包中维护一个文件,文件可以记录节假日的日期,写一个自定义的UDF实现这个功能
    这个方法可以实现,但是过程会有一些繁琐,但是好处是可以复用性强,一次编写,到处使用

    思路二

    维护一张节假日的维表,通过一些sql逻辑实现,优点是实现过程不繁琐,缺点是复用性不强。对于缺点,其实可以把结果输出到一张维表中使用,同时还可以增加一些其他维度,因为生产环境中类似这种时间节假日的维度使用的还挺多。

    四、功能实现

    采用思路二实现,维护一张维表,维表中记录了日期是否为节假日,实现方式也有两种

    方式1:等差求解

    回忆连续登录问题的解法,求等差,找到连续的天数,按照正序排序,返回连续天数的下一天,就是需要的结果
    流程图如下:
    在这里插入图片描述

    日期是否节假日返回值
    06-01106-03
    06-02106-03
    06-03006-03
    06-04106-05
    06-05006-05
    1	select 
    2	  log_date, 
    3	  date_add(log_date, rn) next_work_day 
    4	from ( 
    5	select 
    6	  log_date, 
    7	  row_number() 
    8	  over(partition by start_day order by log_date desc) rn 
    9	from ( 
    10	select 
    11	  log_date, 
    12	  date_sub(log_date, rn) start_day 
    13	from( 
    14	select 
    15	  log_date, 
    16	  row_number() 
    17	  over(order by log_date) rn 
    18	from ( 
    19	select 
    20	  log_date 
    21	from 
    22	  tmp_bdp.tmp_log_date 
    23	) t1 
    24	) t2 
    25	) t3 
    26	) t4 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    方式2:前后相减

    也是模拟连续登录的方式,找到连续天数的下一天,就是要返回的值

    1	select 
    2	  log_date, 
    3	  max(log_date) 
    4	  over(partition by flag order by log_date) next_day 
    5	from ( 
    6		select 
    7		  log_date, 
    8		  sum(if(diff_date > 1, 1, 0)) 
    9		  over(order by log_date) flag 
    10		from ( 
    11			select  
    12			  log_date, 
    13			  datediff(log_date, lag_date) diff_date 
    14			from ( 
    15				select 
    16				  `date` as log_date, 
    17				  lag(`date`, 1, '1970-01-01')  
    18				  over(order by `date`) lag_date 
    19				from 
    20				  bili_dim.dim_date_info_d 
    21				where year(`date`) = 2022 and holiday_type <> 0 
    22			) t1 
    23		) t2 
    24	) t3 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    一文带你了解ADC测试参数有哪些?
    【Python】如何使用PyInstaller打包自己写好的代码
    Python实现BOA蝴蝶优化算法优化支持向量机分类模型(SVC算法)项目实战
    怎么从0到1实现一个PHP框架?
    Tornado 被制裁 还有哪些替代工具?
    云原生Kubernetes:K8S集群各组件服务重启
    AI Studio星河社区生产力实践:基于文心一言快速搭建知识库问答
    【QT】关于QSerialPort的错误处理 (Error Handling)及错误类型
    vue el-form表单嵌套组件时正则校验不生效
    沁恒微电子CH9120是一款网络串口透传芯片
  • 原文地址:https://blog.csdn.net/weixin_46429290/article/details/125477302