复杂查询以获取2个日期/日期时间之间的结果

时间:2016-02-11 16:22:31

标签: mysql datetime

我有这个预订请求: 从2016年2月13日起 - 09:00h到15.02.2016 09:00h租车2天

在确认可用性之前,我想检查我的数据库哪些车辆将忙/已经预留。

我提出这个问题:

select id,modelname from res_reservations 
where resnumber!="9915" and datestart > now() and 
(datestart BETWEEN "2016-02-13 09:00:00" AND "2016-02-15 09:00:00" or
dateend BETWEEN "2016-02-13 09:00:00" AND "2016-02-15 09:00:00") 
order by id ASC 

在数据库res_reservations中我有以下记录:

#id     #modelname      #datestart              #dateend
9912    Volvo           2016-02-25 11:00:00     2016-02-29 09:30:00
9911    Renault         2016-02-12 19:15:00     2016-02-24 12:00:00
9913    Opel            2016-02-16 12:00:00     2016-02-18 12:00:00

我的查询返回此期间没有车辆忙,但这无效,因为ID#9911将在2016-02-12 19:15:00 - 2016-02-24 12:00:00之间保留

如何获得该期间已预订的所有车辆。

感谢您提供任何帮助和建议。

为了澄清,我有一个严肃的理由在数据库中搜索预订车,但不是免费的......

6 个答案:

答案 0 :(得分:3)

你的逻辑错误。您只能检测到部分重叠,并且不允许完全重叠。例如给出新预订的两个日期A + B,以及数据库中现有的X + Y日期,您最终会得到以下可能性:

           x   y
       -------------    
  1    a b |   |           - no overlap
  2    a   b   |          - b = x
  3    a   | b |          - x < b < y
  4    a   |   b          - b = y
  5    a   |   | b        - a < x && b > y
  6        a b |          - full overlap
  7        a   b          - a = x
  8        a   | b        - yada yadayada
  9        |a b| 
  10       | a | b
  11       |   a b
  12       |   | a  b

您只检查a或b在X / Y日期之间的条件,这些条件并未涵盖所有可能性,尤其是#5

答案 1 :(得分:1)

我认为这是一个逻辑问题。查询应如下:

select id,modelname 
from res_reservations 
where resnumber!="9915" and datestart > now() and 
   ("2016-02-13 09:00:00" BETWEEN datestart AND dateend or
    "2016-02-15 09:00:00" BETWEEN datestart AND dateend) 
order by id ASC 

答案 2 :(得分:1)

您的问题是您正在捕获在预订时间内开始或结束的预订,而不是在之前和之后开始的预订。

您想要的逻辑是找到其他预订,其中开始位于您正在查看的期间结束之前,结束位于期间开始之后。这应该是所有重叠的预订。

SELECT id,modelname FROM res_reservations 
WHERE resnumber!="9915" AND datestart > NOW() AND 
(datestart < "2016-02-15 09:00:00" AND 
dateend > "2016-02-13 09:00:00" ) 
ORDER BY id ASC 

答案 3 :(得分:1)

我不确定这是否是您所追求的 - 它正在使用变量,因为我从cmd行运行它,但很容易替换静态值或PHP变量而不是@var

/*
create table if not exists `res_reservations` (
  `id` int(10) unsigned not null auto_increment,
  `modelname` varchar(50) not null default '0',
  `datestart` datetime not null,
  `dateend` datetime not null,
  primary key (`id`)
) engine=innodb auto_increment=7 default charset=utf8;

insert into `res_reservations` (`id`, `modelname`, `datestart`, `dateend`) values
    (1, 'volvo', '2016-02-25 11:00:00', '2016-02-29 09:30:00'),
    (2, 'renault', '2016-02-12 19:15:00', '2016-02-24 12:00:00'),
    (3, 'opel', '2016-02-01 12:00:00', '2016-02-10 12:00:00'),
    (4, 'ferrari', '2016-02-11 15:45:00', '2016-02-13 07:30:00'),
    (5, 'jaguar', '2016-02-14 18:30:00', '2016-02-24 07:00:00'),
    (6, 'austin7', '2016-02-15 10:00:00', '2016-02-15 14:30:00');
*/


/*
select * from `res_reservations`
+----+-----------+---------------------+---------------------+
| id | modelname | datestart           | dateend             |
+----+-----------+---------------------+---------------------+
|  1 | Volvo     | 2016-02-25 11:00:00 | 2016-02-29 09:30:00 |
|  2 | Renault   | 2016-02-12 19:15:00 | 2016-02-24 12:00:00 |
|  3 | Opel      | 2016-02-01 12:00:00 | 2016-02-10 12:00:00 |
|  4 | Ferrari   | 2016-02-11 15:45:00 | 2016-02-13 07:30:00 |
|  5 | Jaguar    | 2016-02-14 18:30:00 | 2016-02-24 07:00:00 |
|  6 | Austin7   | 2016-02-15 10:00:00 | 2016-02-15 14:30:00 |
+----+-----------+---------------------+---------------------+
*/


/* assumed to be the dates the customer wants to book a car from/to */
set @ds='2016-02-11 16:00:00';/* new dates */
set @df='2016-02-13 12:00:00';
set @id=9915;

/* show cars that are busy between dates customer wants */
select `id`,`modelname` as 'booked', `datestart` as 'booked-from', `dateend` as 'return-date'
    from `res_reservations`
    where id!=@id and `datestart` > now() and 
       ( 
            not( @ds not between `datestart` and `dateend` and @df not between `datestart` and `dateend` ) 
        ) or ( 
            @ds > `datestart`
        )
    order by `id` asc;

/*
+----+---------+---------------------+---------------------+
| id | booked  | booked-from         | return-date         |
+----+---------+---------------------+---------------------+
|  2 | Renault | 2016-02-12 19:15:00 | 2016-02-24 12:00:00 |
|  5 | Jaguar  | 2016-02-14 18:30:00 | 2016-02-24 07:00:00 |
+----+---------+---------------------+---------------------+
*/

阅读了你的上一条评论(对延迟道歉,不得不参加会议)我做了一个小小的修改,产生了:

+----+---------+---------------------+---------------------+
| id | booked  | booked-from         | return-date         |
+----+---------+---------------------+---------------------+
|  2 | Renault | 2016-02-12 19:15:00 | 2016-02-24 12:00:00 |
|  3 | Opel    | 2016-02-01 12:00:00 | 2016-02-10 12:00:00 |
|  4 | Ferrari | 2016-02-11 15:45:00 | 2016-02-13 07:30:00 |
+----+---------+---------------------+---------------------+

我也试过了,但它产生了同样的结果:

select * from `res_reservations` where `id` not in (
    select `id` from `res_reservations` where 
        id!=@id and `datestart` > now() and not (
            ( @ds between `datestart` and `dateend` ) or ( @df between `datestart` and `dateend` )
        )
    )

答案 4 :(得分:0)

我猜你的桌子有datestart和dateend,只有在预订时才会填充(对吗?),说过,我想你可能有错误的条件。

1 - datestart不得介于'2016-02-13 09:00:00'和'2016-02-15 09:00:00'之间,所以:

datestart NOT BETWEEN "2016-02-13 09:00:00" AND "2016-02-15 09:00:00"

2 - 你想检查一本书的日期是否实际上没有阻止汽车预订,所以:

AND /* not OR */
dateend NOT BETWEEN "2016-02-13 09:00:00" AND "2016-02-15 09:00:00"

请评论下来,以便我们对此进行排序。

答案 5 :(得分:0)

您的查询仅在datestart或dateend位于区间内时才有效。它将忽略(datestart&lt; min_interval)和(dateend&gt; max_interval)的情况。

您可以添加另一个OR以包含最后一个案例:

debugString()