简体   繁体   中英

Mysql query to see if a booking will conflict with another booking.

I have a table which stores a bunch of books. Customers can book appointments at for any time during the day. I want to make sure that a booking doesnt already exist that will conflict with the new booking.

So I want to find the booking on that date and check that the start and end times dont overlap. I tried doing this with a sub select query to get the bookings from that day and then see if those times overlapped but it didnt seem to be working.

Here is the query I am using. (Status and active are some other fields I need). I find the relevant dates and then see if 8am is between those results individual start/end times or is 9.40am also falls between start/end times.

SELECT event_date, starttime, endtime, status, active 
FROM (SELECT event_date, starttime, endtime, status, active FROM bookings WHERE event_date='2013-07-21' AND status != 'cancelled' AND active !=0 LIMIT 1) AS q1
WHERE ('8:00:00' BETWEEN q1.starttime AND q1.endtime) AND ('9:40:00' BETWEEN q1.starttime AND q1.endtime)

Is this the best method to use? Thanks

WHERE ('8:00:00' BETWEEN q1.starttime AND q1.endtime) AND ('9:40:00' BETWEEN q1.starttime AND q1.endtime)

This implies that the new appointment (8 to 9:40) lies ENTIRELY INSIDE an already existing appt. Instead, you want (I think) to see if either the start OR end of the appt coincides with another one:

WHERE ('8:00:00' BETWEEN q1.starttime AND q1.endtime) OR ('9:40:00' BETWEEN q1.starttime AND q1.endtime)

Also, I'm pretty sure that inner select is unnecessary. I believe this will have the same effect:

SELECT TOP 1 event_date, starttime, endtime, status, active
FROM bookings 
WHERE event_date='2013-07-21' 
    AND status != 'cancelled' 
    AND active != 0
    AND (('8:00:00' BETWEEN q1.starttime AND q1.endtime)
        OR ('9:40:00' BETWEEN q1.starttime AND q1.endtime))
-- if you get a row, then there is a conflicting appt.

To check if one range overlaps another it's easier to think first when it won't overlap and then reverse the condition. It's obvious that:

Two ranges (A,B) don't overlap if A starts after B ends, or if A ends before B starts.

Turning this to SQL you get the following condition for finding an overlapping range:

... WHERE NOT ('8:00:00' > q1.endtime OR '9:40:00' < q1.starttime)

If you want you can rewrite that as:

... WHERE q1.endtime > '8:00:00' AND q1.starttime < '9:40:00'

This way you handle all the corner cases, like one interval completely containing the other.

I ran in the same problem and i used the posted solution but there is another bug that i found if the previous record was lie in the new record as example

The record in the database is starttime 8:30:00 endtime 9:00:00

In this case the record will be added as no matching rows will be found with this

SELECT TOP 1 event_date, starttime, endtime, status, active
FROM bookings 
WHERE event_date='2013-07-21' 
    AND status != 'cancelled' 
    AND active != 0
    AND (('8:00:00' BETWEEN q1.starttime AND q1.endtime)
        OR ('9:40:00' BETWEEN q1.starttime AND q1.endtime))

to fix this issue you need check if the start time or end time it self lies between your new entry like this

SELECT TOP 1 event_date, starttime, endtime, status, active
FROM bookings 
WHERE event_date='2013-07-21' 
    AND status != 'cancelled' 
    AND active != 0
    AND (('8:00:00' BETWEEN q1.starttime AND q1.endtime)
        OR ('9:40:00' BETWEEN q1.starttime AND q1.endtime)
        OR (q1.starttime BETWEEN '8:00:00' AND '9:40:00')
        OR (q1.endtime BETWEEN 8:00:00' AND '9:40:00')
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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