查找预订重叠以检查日期可用性
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-2014 到 14-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 WHEREROOM
= '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' ) > 不显示记录(失败)以上是关于查找预订重叠以检查日期可用性的主要内容,如果未能解决你的问题,请参考以下文章