探讨一个比较复杂的查询

数据库结构

Leave 表结构

类型
id int
start_leave_date date
end_leave_date date

框架

ThinkPHP 5.1

需求

查询时间区间内有请假的数据
例如:我要查询2020-10-04到2020-10-08请假的数据
探讨一个比较复杂的查询

问题点

怎么用时间区间条件查询时间区间数据?例如我想查询 2020-10-1到2020-10-30 的请假数据,表里面只有请假开始和结束的时间(whereBetweenTime 只指定某个字段在某个时间区间)

本作品采用《CC 协议》,转载必须注明作者和本文链接
一个路过的小白
chenvle
最佳答案

明白你意思了,设请假区间为[A, B],查询时间区间为[C, D],其实你就是想求两个区间的交集吧? 那么把我上面的语句补个条件就可以实现了,因为我上面的语句,出现你描述的极端情况的时候,就是区间[A, B]包含区间[C, D]。

Db::table('Leave')
    ->where('start_leave_date','between time',['2015-1-1','2016-1-1'])
    ->whereOr('end_leave_date','between time',['2015-1-1','2016-1-1'])
    ->whereOr(function ($query){
        $query->where('start_leave_date', '<=', '2015-1-1');
        $query->where('end_leave_date', '>=', '2016-1-1');
    })
    ->select();
9个月前 评论
chenvle (楼主) 9个月前
讨论数量: 7

额……建议多看下手册。。www.kancloud.cn/manual/thinkphp5_1... file

9个月前 评论
chenvle (楼主) 9个月前
chenvle (楼主) 9个月前
Db::table('Leave')
    ->where('start_leave_date','between time',['2015-1-1','2016-1-1'])
    ->whereOr('end_leave_date','between time',['2015-1-1','2016-1-1'])
    ->select();

// SQL: SELECT * FROM `Leave` WHERE  `start_leave_date` BETWEEN '2015-1-1' AND '2016-1-1' OR `end_leave_date` BETWEEN '2015-1-1' AND '2016-1-1'
9个月前 评论
chenvle (楼主) 9个月前

明白你意思了,设请假区间为[A, B],查询时间区间为[C, D],其实你就是想求两个区间的交集吧? 那么把我上面的语句补个条件就可以实现了,因为我上面的语句,出现你描述的极端情况的时候,就是区间[A, B]包含区间[C, D]。

Db::table('Leave')
    ->where('start_leave_date','between time',['2015-1-1','2016-1-1'])
    ->whereOr('end_leave_date','between time',['2015-1-1','2016-1-1'])
    ->whereOr(function ($query){
        $query->where('start_leave_date', '<=', '2015-1-1');
        $query->where('end_leave_date', '>=', '2016-1-1');
    })
    ->select();
9个月前 评论
chenvle (楼主) 9个月前

个人觉得业务逻辑有点小问题,按我的理解,比如要查2020-10-1~2020-10-30号请假记录,我觉得应该是查询请假记录中,开始请假时间>=2020-10-1, 并且<=2020-10-30的所有请假记录 ; 而请假的结束时间,是用来计算表示请假了多长时间的; 如果不正确,请指点问题哈

9个月前 评论
chenvle (楼主) 9个月前
chenvle (楼主) 9个月前

Db::table('Leave') ->where('start_leave_date','<=','2016-1-1') ->where('end_leave_date','>=','2015-1-1') ->select();

8个月前 评论

还可以用排除法

一定没有交集的范围是:start_leave_date > 给定的结束时间,end_leave_date < 给定的开始时间

语句:WHERE start_leave_date <= '2020-10-30' AND end_leave_date >= '2020-10-01'

8个月前 评论
chenvle (楼主) 8个月前
秦晓武 7个月前
秦晓武

补个思路

  • 文字化描述题主问题:

    给定数据 [ START, END ]

    求解区间 [ BEGIN, FINISH ]

  • 最佳答案:

    (START between (BEGIN, FINISH)) 
    or (END between (BEGIN, FINISH)) 
    or (START < BEGIN and END > FINISH)
  • 我的想法

    BEGIN < END and FINISH > START
7个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!