Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine multiple room availability queries into one

I'm currently trying to optimize an database by combining queries. But I keep hitting dead ends while optimizing an room availability query.

I have a room availability table where each records states the available number of rooms per date. It's formatted like so:

  • room_availability_id (PK)
  • room_availability_rid (fk_room_id)
  • room_availability_date (2011-02-11)
  • room_availability_number (number of rooms available)

The trouble is getting a list of rooms that are available for EACH of the provided days. When I use IN() like so:

WHERE room_availability_date IN('2011-02-13','2011-02-14','2011-02-15')
AND room_availability_number > 0

If the 14th has availability 0 it still gives me the other 2 dates. But I only want that room_id when it is available on ALL three dates.

Please tell me there is a way to do this in MySQL other than querying each date/room/availability combination separately (that is what is done now :-( )

I tried all sorts of combinations, tried to use room_availability_date = ALL (...), tried some dirty repeating subqueries but to no avail.

Thank you in advance for any thoughts!

like image 215
DaFrenk Avatar asked Feb 26 '23 03:02

DaFrenk


2 Answers

You would need to construct a query to group on the room ID and then check that there is availability on each date, which can be done using the having clause. Leaving the where clause predicate in for room_availability_date will help to keep the query efficient (as indexes etc. can't be used with a having clause easily).

SELECT 
    room_availability_rid

WHERE room_availability_date IN ('2011-02-13','2011-02-14','2011-02-15')
  AND room_availability_number > 0

GROUP BY room_availability_rid 

HAVING count(case room_availability_date when '2011-02-13' THEN 1 END) > 0
   AND count(case room_availability_date when '2011-02-14' THEN 1 END) > 0
   AND count(case room_availability_date when '2011-02-15' THEN 1 END) > 0
like image 190
a'r Avatar answered Mar 12 '23 10:03

a'r


I think I can improve on a'r's answer:

SELECT 
    room_availability_rid, count(*) n

WHERE room_availability_date IN ('2011-02-13','2011-02-14','2011-02-15')
  AND room_availability_number > 0

GROUP BY room_availability_rid 

HAVING n=3

Edit: This of course assumes that there is only one table entry per room per day. Is this a valid assumption?

like image 31
awm Avatar answered Mar 12 '23 10:03

awm