I have these three tables:
hotel |
---|
hotel_id |
hotel_name |
room |
---|
room_id |
hotel_id |
room_price |
---|
room_id |
start_date |
price |
Where ‘start_date’ stores the date the price changed to ‘price’.
I know how to query the database to get the price for a given room_id and given date for the hotel stay. So I can do it, however, when it comes to doing this for a long date range, this becomes impractical.
Therefore how can I query the database so that I get an output like
room_id | date | price |
---|---|---|
1 | check_in | x1 |
… | … | x2 |
… | … | … |
1 | check_out | xm |
2 | check_in | y1 |
… | … | y2 |
… | … | … |
2 | check_out | ym |
… | … | … |
… | … | … |
… | … | … |
n | check_in | z1 |
… | … | z2 |
… | … | … |
n | check_out | zm |
Where ‘check_in’ here is the first night chosen by customer and ‘check_out’ is the last night selected by customer
This would make it a lot easier to calculate total prices for a given room instead of having to do each day individually.
NB: I am using MySQL 5.7
2
Answers
You could either create your date series dynamically, as shown in the answer suggested by Bagus Tesa, or maintain a calendar table. Given that dates play a big part in booking/reservations apps, I would suggest creating a simple calendar table.
For this example I am using a calendar table with just a single dt (
DATE
) column, which you can easily populate with a stored proc (or any other method you choose):Then it is a simple case of a
CROSS JOIN
between the dates for the booking and rooms, and a correlated subquery to retrieve the price per room per day:Note: although the keyword
CROSS
has no significance in MySQL (it’s just an INNER join with no ON clause), I think it makes the intent clear.Here’s a db<>fiddle.
The following query relies on
join
andgroup by
instead of sub query. It took inspiration from generating date series for the date reference. You can replace the date generation with a concrete date table as user1191247 answer suggested.See fiddle: https://www.db-fiddle.com/f/umGDya94iodhMcJbTdvkt6/0
The cornerstone to circumvent
SELECT list is not in GROUP BY clause and contains non-aggregated column
error is usingAny_Value()
. You could have the similar effect by disablingONLY_FULL_GROUP_BY
for the session or permanently.However, do aware that the
Any_Value()
behave differently between Mysql 5.7 and Mysql 8.0 – which kind of a surprise.