我请求你的帮助写一个查询来检查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...
我必须检查房间是否可用。因此,如果我从该查询中得到一些结果,这意味着房间已经被预订......如果我什么也没有得到正好相反...
答案 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);
如果提议预订的任何一天已经分配给另一个预订,则会发生冲突。