查找预订重叠以查看日期可用性

时间:2014-08-28 13:15:52

标签: mysql sql

我请求你的帮助写一个查询来检查MySql中房间的可用性。 目前我有这种表:

 ROOM |    FROM    |     TO
 -----------------------------
  101 | 2014-08-09 | 2014-08-14 
  102 | 2014-08-09 | 2014-08-14 
   ...           ...        ...

所以我将房间101从 09-08-2014 预订到 14-08-2014 ,我查询可用性的查询看起来像=

SELECT order_id FROM booking 
WHERE `ROOM` = '101' 
AND (`FROM` BETWEEN '2014-08-08' AND '2014-08-20') 
AND (`TO` BETWEEN '2014-08-08' AND '2014-08-20')

在上面的示例中,我将检查

之间日期的可用性
   What i trying to archive is this
Order  --------09++++++++++13--------------
Check1 -----08+++++++++++++++++++++++++17-- Not availble
Check2 -----------------12+++++++++++++17-- Not availble
Check3 -----------10----------------------- Not availble
Check4 -----------10+11-------------------- Not availble
Check5 -----------------------14+++++++17-- Available
Check6 --07++++09-------------------------- Not availble
Check7 --------------------------15-------- Availble


SCALE  6-07-08-09-10-11-12-13-14-15-16-17-18-19...

我必须检查房间是否可用。因此,如果我从该查询中得到一些结果,这意味着房间已经被预订......如果我什么也没有得到正好相反...

3 个答案:

答案 0 :(得分:5)

首先,让我们概括一下如何检查区间[a,b][c,d]之间重叠的算法。请注意这些间隔上的方括号,这意味着包含间隔。我们可以使用这个逻辑来检查区间重叠:

a <= d and b >= c

如果该条件为真,那么我们就有重叠。

因此,要将此算法应用于SQL,我们可以执行以下操作:

a = 2014-08-08
b = 2014-08-20
c = FROM
d = TO
SELECT order_id FROM booking 
WHERE NOT EXISTS (
     SELECT * FROM booking
       WHERE ROOM = '101'
         AND '2014-08-08' <= `TO`
         AND '2014-08-20' >= `FROM`
 )
 AND ROOM = '101'

您的方法的另一个问题是您正在检查房间是否可用,并且这里假设如果房间可用,那么您将使用另一个SQL语句进行预订。这是一个有问题的方法,因为您可以双重预订房间。考虑两个进程在相同(或接近相同)时间检查房间可用性的可能性。或者另一个例子是,如果此代码是尚未提交的事务的一部分。另一个过程不会看到你的承诺结果,因此会预订房间。

为了弥补这种有缺陷的方法,我们需要在检查其可用性之前锁定房间行。假设您有一个名为ROOM的其他表,您可以使用&FOR; FOR UP UPDATE&#39;来锁定该行。语句:

SELECT * FROM `ROOM` WHERE ROOM = '101' FOR UPDATE

&#34; FOR UPDATE&#34;将锁定该房间行,这将阻止另一个进程在您的交易完成之前检查该空间是否可用。锁定行后,您可以运行重叠检查。因此,您消除了双重预订问题。

您可以阅读更多关于&#39; FOR UPDATE&#39; here

答案 1 :(得分:0)

如果您想检查整个期间是否有空房,请查找与相关期间重叠的现有预订:

SELECT order_id FROM booking 
WHERE `ROOM` = '101' 
 AND `FROM` <= '2014-08-20' 
 AND `TO` >= 2014-08-08' 

如果查询返回行,则会出现预留冲突,并且空间不可用。

答案 2 :(得分:0)

要测试建议的房间预订是否与现有房间预订冲突(重叠),您需要以下内容:

select count(*) as num_conflicts
from booking
where room = ?proposed_room
    and (from <= ?proposed_to)
    and (to >= ?proposed_from);

如果提议预订的任何一天已经分配给另一个预订,则会发生冲突。