简体   繁体   English

在MySQL中检查日期范围冲突

[英]Checking for date range conflicts in MySQL

I am writing a hotel booking system. 我正在写一个酒店预订系统。 after lots of studying (including stack overflow) i wrote this sql to find out free rooms: 经过大量研究(包括堆栈溢出),我编写了此sql来找出免费房间:

SELECT
*
FROM room
WHERE
    room_id NOT IN (
        SELECT room_id
        FROM bookings
        WHERE
                 checkin <= '$check_in'
            AND checkout >= '$check_out'
    )

but the problem is its not considering the time checking is 12:00:00 and checkout is 11:59:00 但问题是它没有考虑时间检查是12:00:00和结帐是11:59:00

also its not giving the right queries like within the date range its not working like if I book from 15-18 a single room who's number is 501. if I again run a query 17-19 this rooms seems free but in reality it should be occupied. 同样,它没有像日期范围内那样提供正确的查询,也无法正常工作,就像我从15-18预订一个单人房,房间的编号是501。如果我再次运行查询17-19,这个房间似乎是免费的,但实际上应该是占据。

can anyone suggest a very good and effective sql which will get the accurate date so that no clash will happen booking system because the system will be implemented in real so mistakes will cause many issues. 任何人都可以建议一个很好且有效的sql来获取准确的日期,这样就不会发生预订系统冲突,因为该系统将在实际中实施,因此错误会导致很多问题。

thanks in advance 提前致谢

The problem you're having is that your query is not sufficiently robust. 您遇到的问题是您的查询不够可靠。 When you break down the problem, what you have is this: 当您解决问题时,您所拥有的是:

If the range defined by $check_in and $check_out overlaps the range defined by checkin and checkout in any way, then the room is booked. 如果$check_in$check_out定义的范围以任何方式与checkincheckout定义的范围重叠,则将预订房间。 Otherwise, it is free. 否则,它是免费的。

This means that: 这意味着:

  • If $check_in >= checkin and $check_in <= checkout , the room is BOOKED 如果$check_in > = checkin$check_in <= checkout ,客房已预订
  • OR If $check_out >= checkin and $check_out <= checkout , the room is BOOKED 如果$check_out > = checkin$check_out <= checkout ,客房已预订
  • OR If $check_in <= checkin and $check_out >= checkout , the room is BOOKED 如果$check_in <= checkin$check_out > = checkout ,客房已预订

So, you need to represent both of these scenarios in your subquery in order to get the information you're looking for. 因此,您需要在子查询中代表这两种情况,以获得所需的信息。

Also, you will hopefully be using datetime for your comparisons and not just time , otherwise you will have side effects. 另外,希望您将使用datetime进行比较,而不仅仅是time ,否则会产生副作用。

EDIT: SQL Query 编辑:SQL查询

(Keep in mind that there is more than one way to skin a cat, so to speak. I'm just providing an example that keeps with what you already have as much as possible. Once again, I'm also assuming that checkin , checkout , $check_in , and $check_out will all resolve to datetime types) (请记住,可以说有多种方法可以给猫剥皮。我只是提供一个示例,尽可能地保留您已有的猫。我再次假设checkincheckout$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'))

Your original logic was very close, you just need to swap the '$check_in' and '$check_out' values. 您的原始逻辑非常接近,您只需要交换'$check_in''$check_out'值即可。 Ie: 即:

SELECT *
FROM room
WHERE room_id NOT IN
(
    SELECT room_id
    FROM bookings
    WHERE checkin <= '$check_out' AND checkout >= '$check_in'
)

Brian Driscoll's answer focusses on the scenarios that constitute booking conflicts, as so: 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'

However the senarios that constitute no conflict are much simpler. 然而,构成冲突的senarios要简单得多。 There are only two: 只有两个:

---------------|-----Booked-----|---------------
  |----B1----|                             
                                  |----B2----|

Case B1: checkin > '$check_out'
Case B2: checkout < '$check_in'

So the situation where there is no conflict between a booking and a potential booking can be expressed with this SQL: 因此,可以使用以下SQL表示预订和潜在预订之间没有冲突的情况:

checkin > '$check_out' OR checkout < '$check_in'

To check for conflicts instead, we just need to negate this. 要检查冲突,我们只需要对此进行否定即可。 So, using DeMorgans Law, the negation is: 因此,使用德摩根定律,求反是:

checkin <= '$check_out' AND checkout >= '$check_in'

...which arrives at the solution given above. ...得出上面给出的解决方案。

I think this might get you started in the right direction... 我认为这可能会让您朝正确的方向开始...

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')

There are some good ideas here: http://forums.digitalpoint.com/showthread.php?t=63746 这里有一些好主意: http : //forums.digitalpoint.com/showthread.php?t=63746

Also, what column types are you using for your check-in and check-out? 另外,您要使用哪种列类型来进行签入和签出? Are you sure you're passing correctly formatted values in $check_in and $check_out? 您确定要在$ check_in和$ check_out中传递正确格式的值吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM