• MySql对于时间段交集的处理和通用实现方式(MyBatis-Plus)


    问题:一般传统时间筛选是在[ 开始时间 → 结束时间 ]这个区间内的子集,也就是全包含查询方式,这种只会筛选一种情况。如果场景需要是开展一个活动,需要活动时间检索应该但凡包含就返回,也就是需要查询这个时间段有涉及的都需要筛选出来,即返回产生交集的数据

    1.数据分析

    上图是4 - 5月份中开展活动7种时间段,如果以V1的启止时间作为筛选条件,会遇到6种情况

    V2:数据位于查询左侧,不产生交集

            V2结束时间 ≥ V1开始时间

    V3:数据交集查询左侧区域,产生交集

            V1开始时间 ≤ V3结束时间 ≤ V1结束时间,

    V4:数据位于查询的子集内,产生交集

            V4结束时间 ≥ V1结束时间,V4开始时间 ≤ V1开始时间

    V5:数据交集查询右侧区域,产生交集

            V1开始时间 ≤ V5开始时间 ≤ V1结束时间

    V6:数据位于查询右侧,不产生交集

            V1结束时间 ≤ V6开始时间

    V7:数据的部分子集数据位于查询全集区域,产生交集

            V7开始时间 ≥ V1开始时间,V1结束时间 ≤ V7结束时间,

            这 6 种情况,产生交集的只有 4 种,也就是需要把这4种情况的时间段筛选出来,可以归纳为三类场景

    查询时间以 [ startTime, endTime ] 作为筛选条件,开始时间和结束时间为某一个时间段的代称

    1. 全部包含(子集)和左边包含(V3、V4)startTime ≥ 结束时间  ≥ endTime
    2. 右边包含 (V5)startTime ≥ 开始时间  ≥ endTime
    3. 全部包含(被子集)(V7)开始时间 ≥ startTime,endTime  ≥ 结束时间

    2.MySql查询尝试

    创建一个活动表,补充活动开始时间和结束时间,并填充6种情况数据数据

    1. CREATE TABLE `activity` (
    2. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
    3. `activity_start_time` datetime DEFAULT NULL COMMENT '活动开始时间',
    4. `activity_end_time` datetime DEFAULT NULL COMMENT '活动结束时间',
    5. PRIMARY KEY (`id`)
    6. ) ENGINE = InnoDB AUTO_INCREMENT = 0 DEFAULT CHARSET = utf8 COMMENT = '活动';

    我们需要查询的时间段是 [ "2022-04-28 00:00:00" , "2022-05-04 00:00:00" ] 涉及的数据

    1. SELECT * from activity where
    2. # 全部包含(子集)和左边包含
    3. ("2022-04-28 00:00:00" <=activity_end_time and activity_end_time <="2022-05-04 00:00:00")
    4. # 右边包含
    5. or ("2022-04-28 00:00:00"<=activity_start_time and activity_start_time <="2022-05-04 00:00:00")
    6. # 全部包含(被子集)
    7. or (activity_start_time <= "2022-04-28 00:00:00" and "2022-05-04 00:00:00" <= activity_end_time)

    3.通用方法

    Mysql通用模板

    1. SELECT * from activity where
    2. # 全部包含(子集)和左边包含
    3. ("开始时间" <=activity_end_time and activity_end_time <="结束时间")
    4. # 右边包含
    5. or ("开始时间"<=activity_start_time and activity_start_time <="结束时间")
    6. # 全部包含(被子集)
    7. or (activity_start_time <= "开始时间" and "结束时间" <= activity_end_time)

     MyBatis-plus通用功能

    1. /**
    2. * 时间交集,与当前时间有交集筛选
    3. *
    4. * @param beginColumn 指定开始列
    5. * @param endColumn 指定结束列
    6. * @param startTime 开始时间
    7. * @param endTime 结束时间
    8. * @param 类型
    9. * @param 列类型
    10. * @return
    11. */
    12. public Consumer> timeIntersection(
    13. SFunction beginColumn, SFunction endColumn, Date startTime, Date endTime) {
    14. return wrapper -> {
    15. //全部包含(子集)和左边包含
    16. wrapper.and(x -> x.ge(endColumn, startTime).le(endColumn, endTime))
    17. //右边包含
    18. .or(x -> x.ge(beginColumn, startTime).le(beginColumn, endTime))
    19. //全部包含(被子集)
    20. .or(x -> x.le(beginColumn, startTime).ge(endColumn, endTime));
    21. };
    22. }

    使用方式

    1. @Test
    2. public void testTime() throws Exception{
    3. //数据准备
    4. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    5. Date startTime =sdf.parse("2022-04-28 00:00:00");
    6. Date endTime =sdf.parse("2022-05-04 00:00:00");
    7. //使用方式
    8. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper()
    9. .func(startTime != null && endTime != null, timeIntersection(
    10. Activity::getActivityStartTime, Activity::getActivityEndTime, startTime, startTime));
    11. }
    12. /**
    13. * 时间交集,与当前时间有交合条件
    14. *
    15. * @param beginColumn 指定开始列
    16. * @param endColumn 指定结束列
    17. * @param beginTime 开始时间
    18. * @param endTime 结束时间
    19. * @param 类型
    20. * @param 列类型
    21. * @return
    22. */
    23. public static Consumer> timeIntersection(
    24. SFunction beginColumn, SFunction endColumn, Date beginTime, Date endTime) {
    25. return wrapper -> {
    26. //全部包含(子集)和左边包含
    27. wrapper.and(x -> x.ge(endColumn, beginTime).le(endColumn, endTime))
    28. //右边包含
    29. .or(x -> x.ge(beginColumn, beginTime).le(beginColumn, endTime))
    30. //全部包含(被子集)
    31. .or(x -> x.le(beginColumn, beginTime).ge(endColumn, endTime));
    32. };
    33. }
    34. @Data
    35. @NoArgsConstructor
    36. @AllArgsConstructor
    37. public class Activity{
    38. /** 主键 */
    39. private Long id;
    40. /** 开始时间 */
    41. private Date activityStartTime;
    42. /** 结束时间 */
    43. private Date activityEndTime;
    44. }

     

  • 相关阅读:
    【重学C++】02 脱离指针陷阱:深入浅出 C++ 智能指针
    介绍一下cpu主频越高越好吗?
    Springboot学习
    Redis设计与实现(3)字典
    eyb:SpringSecurity:Oauth2协议
    消息队列一文全解!!!
    【Hyperledger Fabric 学习】安装和运行
    Lilishop 开源商城系统代码审计
    基于PLC的矿泉水自动瓶装控制系统设计
    50.【动态二维数组的运用】
  • 原文地址:https://blog.csdn.net/mcband/article/details/138046938