i asking your help to write an query for checking the availability of an room inside MySql. Currently i have this kind of table:
ROOM | FROM | TO
-----------------------------
101 | 2014-08-09 | 2014-08-14
102 | 2014-08-09 | 2014-08-14
... ... ...
So i have the room 101 booked from 09-08-2014 to 14-08-2014, my query to check availability is look like =
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')
In the above example i will check the availability in the dates between
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...
I must check if the room is available. So if i get some result out of that query that means that the room is already booked... if i get nothing just the opposite...
First, let's generalize an algorithm for how to check for an overlap between intervals [a,b]
and [c,d]
. Note the square braces on those intervals, which means an inclusive interval. We can use this logic to check for an interval overlap:
a <= d and b >= c
If that condition is true, then we have an overlap.
So to apply this algorithm to SQL, we could do something like this:
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'
The other problem with your approach is that you are checking to see if a room is available, and the assumption here is that if the room is available, then you will book it with another SQL statement. This is a problematic approach, because there is the possibility that you could double book a room. Consider the possibility that two processes check for room availability at the same (or close to the same) time. Or another example would be if this code were part of a transaction that hadn't been committed yet. The other process wouldn't see your committed result, and thus, would double book the room.
To remedy this flawed approach, we need to lock the room row before we check for its availability. Assuming you have some other table called ROOM, you could lock the row using a 'FOR UPDATE' statement:
SELECT * FROM `ROOM` WHERE ROOM = '101' FOR UPDATE
The "FOR UPDATE" will lock that room row, which will prevent another process from checking that room for availability until your transaction is finished. After you lock the row, you could run your overlap check. Thus, you eliminate the double booking problem.
You can read more about 'FOR UPDATE' here.
If you want to check whether room is available for the whole period, look for existing bookings that overlap with period in question:
SELECT order_id FROM booking
WHERE `ROOM` = '101'
AND `FROM` <= '2014-08-20'
AND `TO` >= 2014-08-08'
If query returns rows, you have a reservation conflict and room is not available.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With