简体   繁体   中英

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!

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

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?

You can group by room ID, generate a list of dates available, and then see if all the dates you need are included.

This will give you a list of dates each room is available:

select `room_availability_rid`,group_concat(`room_ availability_date`) as `datelist`
       from `table` where room_availability_number>0 
       group by `room_availability_rid`

Then we can add a having clause to get the rooms that are available on all of the dates we need:

select `room_availability_rid`,group_concat(`room_ availability_date`) as `datelist`
        from `table` where room_availability_number>0
        group by `room_availability_rid`
        having find_in_set('2011-02-13',`datelist`) and
               find_in_set('2011-02-14',`datelist`) and
               find_in_set('2011-02-15',`datelist`)

This should work. Test it for me will ya? :)

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