I would suggest storing the opening times, and then the time each restaurant stays open, instead of the closing time. This will make it easier to make calculations on the opening times, and it will also avoid the ambiguity with restaurants that stay open after midnight.
Example design, using MySQL:
CREATE TABLE restaurant_chains (
id int AUTO_INCREMENT PRIMARY KEY,
name varchar(20)
);
CREATE TABLE restaurant_branches (
id int AUTO_INCREMENT PRIMARY KEY,
chain_id int NOT NULL,
locality varchar(20)
);
CREATE TABLE opening_times (
id int AUTO_INCREMENT PRIMARY KEY,
branch_id int NOT NULL,
day_of_week int NOT NULL,
open_time time,
open_duration time
);
Make sure to add the relevant foreign key and unique constraints. You could also add a check constraint so that day_of_week
is always between 1 and 7, since that would represent the weekday (1 for Sunday, 2 for Monday, etc).
Now let's fill our database with some test data:
INSERT INTO restaurant_chains VALUES (NULL, 'Chain A');
INSERT INTO restaurant_chains VALUES (NULL, 'Chain B');
INSERT INTO restaurant_branches VALUES (NULL, 1, 'Branch 1 for A');
INSERT INTO restaurant_branches VALUES (NULL, 1, 'Branch 2 for A');
INSERT INTO restaurant_branches VALUES (NULL, 2, 'Branch 1 for B');
INSERT INTO restaurant_branches VALUES (NULL, 2, 'Branch 2 for B');
INSERT INTO opening_times VALUES (NULL, 1, 1, '10:00:00', '04:00:00');
INSERT INTO opening_times VALUES (NULL, 1, 1, '19:00:00', '03:00:00');
INSERT INTO opening_times VALUES (NULL, 1, 2, '08:00:00', '12:30:00');
INSERT INTO opening_times VALUES (NULL, 2, 1, '19:00:00', '05:15:00');
INSERT INTO opening_times VALUES (NULL, 2, 2, '19:00:00', '04:00:00');
The following query returns the opening time, closing time, and duration for all restaurants:
SELECT rb.locality,
ot.day_of_week,
ot.open_time,
ADDTIME(ot.open_time, open_duration) AS close_time,
ot.open_duration
FROM opening_times ot
JOIN restaurant_branches rb ON (rb.id = ot.branch_id)
JOIN restaurant_chains rc ON (rc.id = rb.chain_id);
+----------------+-------------+-----------+------------+---------------+
| locality | day_of_week | open_time | close_time | open_duration |
+----------------+-------------+-----------+------------+---------------+
| Branch 1 for A | 1 | 10:00:00 | 14:00:00 | 04:00:00 |
| Branch 1 for A | 1 | 19:00:00 | 22:00:00 | 03:00:00 |
| Branch 1 for A | 2 | 08:00:00 | 20:30:00 | 12:30:00 |
| Branch 2 for A | 1 | 19:00:00 | 24:15:00 | 05:15:00 |
| Branch 2 for A | 2 | 19:00:00 | 23:00:00 | 04:00:00 |
+----------------+-------------+-----------+------------+---------------+
5 rows in set (0.00 sec)
Then the following query would return the opening hours of a specific restaurant, on a specific day:
SELECT ot.open_time,
DATEADD(ot.open_time, open_duration) AS close_time,
ot.open_duration
FROM opening_times ot
JOIN restaurant_branches rb ON (rb.id = ot.branch_id)
JOIN restaurant_chains rc ON (rc.id = rb.chain_id)
WHERE rb.id = 1 AND ot.day_of_week = 1;
+-----------+------------+---------------+
| open_time | close_time | open_duration |
+-----------+------------+---------------+
| 10:00:00 | 14:00:00 | 04:00:00 |
| 19:00:00 | 22:00:00 | 02:00:00 |
+-----------+------------+---------------+
2 rows in set (0.00 sec)