Reputation: 5348
I have a restaurants
table and a bookings
table. Each booking stores a date, number of persons, and one of 3 time slots (event_time
). An example row:
id | restaurant_id | date | number_of_persons | event_time
7 2 2019-09-12 00:00:00 15 2
I want to return all restaurants that has free seats bookable for any event_time on a certain date.
Restaurants with no bookings are returned using left
join.
I can get bookings with the join and do SUM(number_of_persons)
and check if max capacity has been met for each event_time that has bookings. The problem is that any event_time having 0 bookings is not included in the result (since it is non existant), so it doesn't count.
The current query excludes restaurants which are fully booked for the event_times which has bookings. So if event_time
1 and 2 are fully booked, and event_time
3 is free and bookable, that restaurant is still excluded (wrongly).
Here is the current query:
select restaurants.id, `restaurants`.title,
number_of_seats_max,
num_persons_booked,
number_of_seats_max - num_persons_booked AS free_seats_left,
event_time
from `restaurants`
left join ( select `restaurant_id`, `b`.`event_time`,
SUM(b.number_of_persons) as num_persons_booked
from `bookings` as `b`
where `event_date` = "2019-9-12"
group by `b`.`event_time`, `restaurant_id`
order by num_persons_booked
) as `bookings_summaries`
on `restaurants`.`id` = `bookings_summaries`.`restaurant_id`
having number_of_seats_max - num_persons_booked > 0 // <-- not fully booked
or num_persons_booked IS NULL //<-- no bookings
I have a fiddle here.
The logic I think is needed is: Return restaurants which have bookings and:
or
But I don't know how to implement it. I appreciate any help!
Upvotes: 0
Views: 39
Reputation: 1153
You need to assign event_time 1,2,3 for every place before left join with booking_summerise then only it gives results for every event.
select restaurants.id, `restaurants`.title,
number_of_seats_max,
restaurants.event_time,
IFNULL(num_persons_booked,0) AS num_persons_booked,
number_of_seats_max - IFNULL(num_persons_booked,0) AS free_seats_left
from ((select *,("1") AS event_time from restaurants) UNION ALL (select *,("2") AS event_time from restaurants) UNION ALL (select *,("3") AS event_time from restaurants)) AS restaurants
left join ( select `restaurant_id`, `b`.`event_time`, SUM(b.number_of_persons) as num_persons_booked
from `bookings` as `b`
where `event_date` = "2019-9-12"
group by `b`.`event_time`, `restaurant_id`
order by num_persons_booked
) as `bookings_summaries`
on `restaurants`.`id` = `bookings_summaries`.`restaurant_id` AND
`restaurants`.`event_time` = `bookings_summaries`.`event_time`
having number_of_seats_max - num_persons_booked > 0
or num_persons_booked IS NULL
ORDER BY `restaurants`.`id`
Upvotes: 1