Let's say we want to make the most efficient hotel website. On this website, rooms may have different prices according to "how many people", dates and days of the week. What is the most efficient way to store and process them?
The first method -> price for every specific date;
date | room_id | price | price_for_2_people |
---|---|---|---|
01-01-2023 | 1 | 20.00 | 40.00 |
02-01-2023 | 1 | 20.00 | 40.00 |
or -> price for date range;
date_start | date_end | room_id | price | price_for_2_people | price_for_weekend |
---|---|---|---|---|---|
01-01-2023 | 01-03-2023 | 1 | 20.00 | 40.00 | 30.00 |
01-03-2023 | 01-07-2023 | 1 | 30.00 | 50.00 | 40.00 |
Please note that from time to time admin users may enter prices for only a single day, and sometimes set prices in wide ranges.
Also, in the second option, calculating the price for a single day may seem much more efficient on the SQL side. Because if you are searching for specific date, instead of searching over 1000 lines, it is much faster to search in 20 30 lines. But if the customer wants to make a 7-day reservation, it will be necessary to collect the prices by searching the days one by one on the coding side. Because the start day and the end day can be in different rows (the price may be 30 euros for the first 3 days, then 40 euros).
A few more variables may come into this table, but these will be the main ones. How should I configure the database so that there are no errors and the algorithm runs the most efficient? Also I would like to escape date collisions and blank dates.
I expect finding best way to create hotel reservations database.
How about something like this?
room_id | room_type | capacity |
---|---|---|
1 | Single | 1 |
2 | Double | 2 |
3 | Suite | 4 |
period_id | date_start | date_end |
---|---|---|
1 | 2023-01-01 | 2023-01-31 |
2 | 2023-02-01 | 2023-02-28 |
3 | 2023-03-01 | 2023-03-31 |
price_id | room_id | period_id | price | price_for_2_people | price_for_weekend |
---|---|---|---|---|---|
1 | 1 | 1 | 20.00 | 40.00 | 30.00 |
2 | 1 | 2 | 30.00 | 50.00 | 40.00 |
3 | 2 | 1 | 40.00 | 60.00 | 50.00 |
Key Points to Remember:
Avoid Overlapping Dates: When you create or update your price_periods
table, ensure there are no overlapping periods for the same room. You should include a check in your application logic to prevent this.
Handle Date Gaps: If a room should be available every day, ensure there are no gaps between periods. The end date of one period should be one day before the start date of the next for a given room.
Optimize for Speed: If you often retrieve prices based on dates, consider indexing the date_start
and date_end
columns in the price_periods
table. This would significantly speed up your queries.
Choose the Right Database Type: This design is suitable for SQL databases. However, if your usage pattern doesn't align with SQL, a NoSQL database might be a better option, offering more flexibility in data structures.
Here are some Example SQL SELECT
Queries to illustrate:
SELECT *
FROM rooms
WHERE room_id = 1;
SELECT r.room_id, r.room_type, p.price, p.price_for_2_people, p.price_for_weekend
FROM rooms r
JOIN prices p ON r.room_id = p.room_id
WHERE r.room_id = 1;
SELECT r.room_id, r.room_type, p.price, p.price_for_2_people, p.price_for_weekend
FROM rooms r
JOIN prices p ON r.room_id = p.room_id
JOIN price_periods pp ON p.period_id = pp.period_id
WHERE r.room_id = 1 AND '2023-01-15' BETWEEN pp.date_start AND pp.date_end;
SELECT r.room_id, r.room_type, p.price, p.price_for_2_people, p.price_for_weekend
FROM rooms r
JOIN prices p ON r.room_id = p.room_id
JOIN price_periods pp ON p.period_id = pp.period_id
WHERE '2023-01-15' BETWEEN pp.date_start AND pp.date_end;
SELECT r.room_id, r.room_type, p.price, p.price_for_2_people, p.price_for_weekend, pp.date_start, pp.date_end
FROM rooms r
JOIN prices p ON r.room_id = p.room_id
JOIN price_periods pp ON p.period_id = pp.period_id
WHERE r.room_id = 1 AND pp.date_start >= '2023-01-01' AND pp.date_end <= '2023-01-31';