I have the following MySQL query:
SELECT work_from, work_until, restaurant_id, from_date, to_date FROM restaurant_working_times
WHERE restaurant_id = ?
and restaurant_id is not null
and `week_day` = ?
and `is_closed` = 0
and ((from_date <= ? and until_date >= ?) or (from_date is null and until_date is null))
ORDER BY (from_date IS NOT NULL AND until_date IS NOT NULL) DESC
LIMIT 1
The logic of the query is to get opening hours for the restaurant. There're 2 types of open hours:
- Permanent. It is default opening hours for restaurant for every day
- Specific. It is a row that contains the range between
from_dateanduntil_datedates when this schedule works.
Query gets the rows which:
- has current day of week in ISO format ISO (1 => Monday etc)
- where current date is in the range of
from_dateanduntil_date(custom restaurant schedule) orfrom_dateanduntil_dateequals toNULL(default restaurant schedule) - where
is_closedcolumn equals to0(if the column equals to0, then the restaurant closed today)
And then I sort the result by from_date and until_date and limit the result by 1 row, so if restaurant has a custom schedule, then I'll take the row that contains custom schedule for today. If no, I'll take the row with default schedule.
The problem: this query allows to get opening hours for certain restaurant (I have to execute this query for each restaurant). It makes the N+1 problem if I want to get the list of the open restaurants.
Question: what is the query that will find open restaurants?
restaurant_working_times table schema
+----+---------------+----------+------------+------------+-----------+------------+-----------+
| id | restaurant_id | week_day | from_date | until_date | from_hour | until_hour | is_closed |
+----+---------------+----------+------------+------------+-----------+------------+-----------+
| 8 | 5 | 1 | NULL | NULL | 10:00:00 | 22:00:00 | 0 |
| 15 | 5 | 1 | 2020-09-01 | 2020-09-10 | 10:00:00 | 22:00:00 | 0 |
| 9 | 5 | 2 | NULL | NULL | 10:00:00 | 22:00:00 | 0 |
| 16 | 5 | 2 | 2020-09-01 | 2020-09-10 | 10:00:00 | 22:00:00 | 0 |
| 10 | 5 | 3 | NULL | NULL | 10:00:00 | 22:00:00 | 0 |
| 17 | 5 | 3 | 2020-09-01 | 2020-09-10 | 10:00:00 | 22:00:00 | 0 |
| 11 | 5 | 4 | NULL | NULL | 10:00:00 | 22:00:00 | 0 |
| 18 | 5 | 4 | 2020-09-01 | 2020-09-10 | 10:00:00 | 22:00:00 | 0 |
| 12 | 5 | 5 | NULL | NULL | 10:00:00 | 22:00:00 | 0 |
| 19 | 5 | 5 | 2020-09-01 | 2020-09-10 | 10:00:00 | 22:00:00 | 0 |
| 13 | 5 | 6 | NULL | NULL | 10:00:00 | 22:00:00 | 0 |
| 20 | 5 | 6 | 2020-09-01 | 2020-09-10 | 10:00:00 | 22:00:00 | 0 |
| 14 | 5 | 7 | NULL | NULL | 10:00:00 | 22:00:00 | 0 |
| 21 | 5 | 7 | 2020-09-01 | 2020-09-10 | 10:00:00 | 22:00:00 | 0 |
+----+---------------+----------+------------+------------+-----------+------------+-----------+
I want to get the output with the following columns:
id, restaurant_id, from_hour, until_hour
There should be only open restaurants, so open restaurant means that we found the row with restaurant_id where current time greater than from_hour and less than until_hour. Also I should repeat that "custom" schedule has a higher priority than "default" schedule. "custom" schedule means that from_date and until_date are not equal to null. If there's no custom schedule for the day — we take "default" schedule, if there's no default schedule — the restaurant is closed today.