如何在MySQL中不重叠地存储日期和时间范围

时间:2016-05-31 02:09:16

标签: mysql

我正在尝试找到正确的查询来检查MySQL表中的日期和时间范围是否重叠,这是表格:

id      pickup_date     pickup_time     return_date     return_time
1       2016-05-01      12:00:00        2016-05-31      13:00:00
2       2016-07-01      12:00:00        2016-07-04      15:00:00

以下是有关每个预订的数据,需要根据“预订”表进行检查:

pickup_date = '2016-04-01';
pickup_time = '12:00:00'
return_date = '2016-05-01';
return_time = '13:00:00'

使用此数据,预留与数据库中的预留重叠。请注意:新预订可以是过去或将来。

编辑(由spencer7593提议,这是迄今为止的工作版本):

    SET @new_booking_pickup_date = '2016-04-01';
    SET @new_booking_pickup_time = '12:00:00';
    SET @new_booking_return_date = '2016-05-01';
    SET @new_booking_return_time = '13:00:00';

    SELECT * FROM Reservation WHERE NOT 
( CONCAT(@new_booking_pickup_date,' ',@new_booking_pickup_time) > CONCAT(return_date,' ',return_time) + INTERVAL 0 DAY OR CONCAT(@new_booking_return_date,' ',@new_booking_return_time) < CONCAT(pickup_date,' ',pickup_time) + INTERVAL 0 DAY);

,所以这个查询会产生:

id      pickup_date     pickup_time     return_date     return_time
1       2016-05-01      12:00:00        2016-05-31      13:00:00

1 个答案:

答案 0 :(得分:1)

很容易确定某个特定时期是否与另一个时期重叠。

为了便于表达比较,对于时段1,我们将开头和结尾用b1和e1表示。对于时期2,b2和e2。

如果满足以下条件,则不会重叠:

  b1 > e2 OR e1 < b2

(我们可以狡辩是否将b1和e2的相等视为重叠,并根据需要进行调整。)

如果存在重叠,则该测试的否定将返回TRUE

 NOT (b1 > e2 OR e1 < b2)

因此,要查明是否存在与建议期间重叠的行,我们需要一个测试是否返回行的查询...

假设我们要检查的表格有st列和et(DATETIME),表示每个句点的开头和结尾。

查找与b1e1

限定的建议时段重叠的行
  SELECT t.* FROM t WHERE NOT (b1 > t.et OR e1 < t.st)

因此,对于只检查是否存在重叠行的查询,我们可以执行以下操作:

  SELECT EXISTS (SELECT 1 FROM t WHERE NOT (b1 > t.et OR e1 < t.st))

这非常简单。

当我们将日期时间的datetime组件的(无法解释的)拆分调整为单独的列时,它看起来会变得复杂得多(如图所示)问题)。

将单独的日期和时间值组合在一起成为DATETIME数据类型的单个值只是一件简单的事。

我们需要做的就是将上面的查询替换为适当的转换,例如

  st =>  CONCAT(pickup_date,' ',pickup_time) + INTERVAL 0 DAY
  et =>  CONCAT(return_date,' ',return_time) + INTERVAL 0 DAY

b1e1相同。

做出替代,提出最终查询,留给任何人决定将日期和时间存储为单独的列是一个好主意。