[英]Checking for date range conflicts in MySQL
我正在写一个酒店预订系统。 经过大量研究(包括堆栈溢出),我编写了此sql来找出免费房间:
SELECT
*
FROM room
WHERE
room_id NOT IN (
SELECT room_id
FROM bookings
WHERE
checkin <= '$check_in'
AND checkout >= '$check_out'
)
但问题是它没有考虑时间检查是12:00:00和结帐是11:59:00
同样,它没有像日期范围内那样提供正确的查询,也无法正常工作,就像我从15-18预订一个单人房,房间的编号是501。如果我再次运行查询17-19,这个房间似乎是免费的,但实际上应该是占据。
任何人都可以建议一个很好且有效的sql来获取准确的日期,这样就不会发生预订系统冲突,因为该系统将在实际中实施,因此错误会导致很多问题。
提前致谢
您遇到的问题是您的查询不够可靠。 当您解决问题时,您所拥有的是:
如果$check_in
和$check_out
定义的范围以任何方式与checkin
和checkout
定义的范围重叠,则将预订房间。 否则,它是免费的。
这意味着:
$check_in
> = checkin
和$check_in
<= checkout
,客房已预订 $check_out
> = checkin
和$check_out
<= checkout
,客房已预订 $check_in
<= checkin
和$check_out
> = checkout
,客房已预订 因此,您需要在子查询中代表这两种情况,以获得所需的信息。
另外,希望您将使用datetime
进行比较,而不仅仅是time
,否则会产生副作用。
编辑:SQL查询
(请记住,可以说有多种方法可以给猫剥皮。我只是提供一个示例,尽可能地保留您已有的猫。我再次假设checkin
, checkout
, $check_in
和$check_out
将全部解析为datetime
类型)
SELECT *
FROM room
WHERE room_id NOT IN
(SELECT room_id
FROM bookings
WHERE
(checkin <= '$check_in' AND checkout >= '$check_in') OR
(checkin <= '$check_out' AND checkout >= '$check_out') OR
(checkin >= '$check_in' AND checkout <= '$check_out'))
您的原始逻辑非常接近,您只需要交换'$check_in'
和'$check_out'
值即可。 即:
SELECT *
FROM room
WHERE room_id NOT IN
(
SELECT room_id
FROM bookings
WHERE checkin <= '$check_out' AND checkout >= '$check_in'
)
Brian Driscoll的答案侧重于构成预订冲突的方案,因此:
---------------|-----Booked-----|---------------
|----A1----|
|----A2----|
|--A3--|
|----------A4----------|
Case A2 & A3: checkin <= '$check_in' AND checkout >= '$check_in'
Case A1 & A3: checkin <= '$check_out' AND checkout >= '$check_out'
Case A4: checkin >= '$check_in' AND checkout <= '$check_out'
然而,构成不冲突的senarios要简单得多。 只有两个:
---------------|-----Booked-----|---------------
|----B1----|
|----B2----|
Case B1: checkin > '$check_out'
Case B2: checkout < '$check_in'
因此,可以使用以下SQL表示预订和潜在预订之间没有冲突的情况:
checkin > '$check_out' OR checkout < '$check_in'
要检查冲突,我们只需要对此进行否定即可。 因此,使用德摩根定律,求反是:
checkin <= '$check_out' AND checkout >= '$check_in'
...得出上面给出的解决方案。
我认为这可能会让您朝正确的方向开始...
SELECT R.*
FROM room AS R
LEFT OUTER JOIN bookings AS B USING (room_id)
WHERE B.room_id IS NULL
OR (B.checkout < '$check_in'
AND B.checkin > '$check_out')
这里有一些好主意: http : //forums.digitalpoint.com/showthread.php?t=63746
另外,您要使用哪种列类型来进行签入和签出? 您确定要在$ check_in和$ check_out中传递正确格式的值吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.