user3407278
user3407278

Reputation: 1273

mysql query for getting all rooms which are not booked between a date range not giving expected results

I'm creating a booking system and it has 2 tables

rooms

id  | name          | no_of_rooms   
1   | Lake View     | 4
2   | Royale        | 2
3   | Sky View      | 6

bookings

id |room_id     | start             | end           | total_rooms
4  |1           | 2015-08-13        | 2015-08-14    | 2
5  |2           | 2015-08-20        | 2015-08-22    | 1
6  |2           | 2015-08-01        | 2015-08-13    | 1

and when creating a new booking on the search page I want to find the available rooms that is available within this date range

SEARCH VALUES start : 2015-08-11 end : 2015-08-12

Expected Result

id | name       | no_of_rooms       | available_rooms
1  | Lake View  | 4                 | 4
2  | Royale     | 2                 | 1
3  | Sky View   | 6                 | 6

Result I got

id  | name          | no_of_rooms   | available_rooms
1   | Lake View     | 4             | 0
2   | Royale        | 2             | 1
3   | Skyview       | 6             | 0

Here's the code I wrote for room availability

SELECT 
    r.id, 
    r.name,
    r.no_of_rooms,
    IFNULL(sum(b.total_rooms),0) as available_rooms
FROM rooms r
LEFT JOIN bookings b ON r.id = b.room_id AND 
(
    (b.start <= "2015-08-11" AND b.end >= "2015-08-11")
    OR
    (b.start <= "2015-08-12" AND b.end >= "2015-08-12")
)
GROUP BY r.id

I also don't want the to show unavailable rooms.No matter what I tried the results are completely wrong.Hope you guys can help me out!

Upvotes: 2

Views: 1544

Answers (1)

Giorgos Betsos
Giorgos Betsos

Reputation: 72175

You can try:

SELECT r.id AS roomID, r.name, r.no_of_rooms, 
       r.no_of_rooms - COALESCE(t.bookedRooms,0) AS available_rooms
FROM rooms AS r
LEFT JOIN (
   SELECT room_id, SUM(total_rooms) AS bookedRooms
   FROM bookings
   WHERE `start` < '2015-08-14' AND `end` > '2015-08-11'
   GROUP BY room_id ) AS t
ON r.id = t.room_id
WHERE r.no_of_rooms - COALESCE(t.bookedRooms,0) > 0

The key to finding booked rooms for the specified period is the following predicate:

`start` <= '2015-08-12' AND `end` >= '2015-08-11'

The above gets all rooms whose booking period overlaps, even for one day, with the specified period.

Using a GROUP BY on room_id we can get the total sum of booked rooms per room_id for the period specified.

To get the expected result set, we can just do a LEFT JOIN with the derived table of booked aggregates and simply subtract the sum of booked rooms from the number of available rooms.

Demo here

Upvotes: 4

Related Questions