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

Posted

技术标签:

【中文标题】查找预订重叠以检查日期可用性【英文标题】:Find booking overlaps to check dates availability 【发布时间】:2014-08-28 13:15:52 【问题描述】:

我请求您帮助编写查询以检查 mysql 中房间的可用性。 目前我有这种表:

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

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

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...

我必须检查房间是否可用。所以如果我从那个查询中得到一些结果,这意味着房间已经被预订了......如果我什么都没有得到相反的结果......

【问题讨论】:

检查列名。在查询中你用小写字母写。 啊哈哈。现在你能帮我解决这个问题吗? 你的问题能说清楚吗 已经尝试使用 SELECT order_id FROM booking WHERE ROOM = '101' AND (FROM BETWEEN '2014-08-08' AND '2014-08-20') OR (TO在“2014-08-08”和“2014-08-20”之间)。不工作... 感谢您的回答,我会尽快检查所有内容。现在我必须走了…… 【参考方案1】:

首先,让我们概括一个算法,用于检查区间[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 UPDATE”语句锁定该行:

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

“FOR UPDATE”将锁定该房间行,这将阻止另一个进程在您的事务完成之前检查该房间的可用性。锁定行后,您可以运行重叠检查。因此,您消除了重复预订问题。

您可以阅读有关“更新”here 的更多信息。

【讨论】:

order_id 与子查询有什么关系? ...这不会根据子查询的结果选择全部或不选择 order_id 吗? @FuzzyTree - 我不太了解 OP 数据上下文中的 order_id。我只是以他们的原始查询为基础。 op 的问题不清楚,但我认为他们可能正在寻找 select not exists(...) 并且 order_id 是预订的 ID @FuzzyTree - 是的,好点,我不确定。无论如何,我只是试图概括该方法,以便 OP 可以使其适应他们的特定需求。我还觉得指出锁定问题很重要,如果在高并发系统中处理不当,这可能是一个主要问题。 工作并感谢有关“更新”的提示,我会尽快检查:D【参考方案2】:

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

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

如果查询返回行,则您有预订冲突并且房间不可用。

【讨论】:

【参考方案3】:

要测试提议的房间预订是否与现有的房间预订冲突(重叠),您需要这样的东西:

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

当提议的预订的任何一天已经分配给另一个预订时,这就会算作冲突。

【讨论】:

很明显,?proposed_* 不是 SQL,但这是您可以在某些宿主语言的准备好的语句中使用参数的地方。 感谢您的代码工作,但我不需要计数,但订单 ID :D 从预订中选择order_id ROOM= '101' and (FROM = '2014-08-15' ) > 不显示记录(失败)

以上是关于查找预订重叠以检查日期可用性的主要内容,如果未能解决你的问题,请参考以下文章

我想通过检查预订日期或即将到来的日期的时间段可用性来更新我的会议室预订表

时间段预订脚本 - 检查可用性

已解决触发器以检查预留 mysql 的可用性

验证以检查与以前的预订不存在重叠

如何在 Django 中检查或设置房间可用性

用于检查房间可用性的 SQL 查询