# Diseño del sistema de reserva de hotel: reserva que utiliza varias habitaciones

Frecuentes

Visto 2,050 veces

2

I'm looking for some design advice on a hotel room like booking system. I've read a lot of stuff on this so far and I've got a query which returns a list of rooms which are available for a certain date range.

My search currently only returns rooms which are available for the entire booking period the user is searching for. I'd like to expand this so I can fulfill the request with multiple rooms. I.e. User searches for a date range and Room 1 is available for the first 2 days, then they would need to be transferred to Room 2 for the last 2 days.

I currently do my availability lookup using the following query;

```
Dim available = From k In rooms _
Group Join r In db.Reservations.Where(Function(fx) (fx.DateIn >= Date_From And fx.DateIn < Date_To) Or (fx.DateOut > Date_From And fx.DateOut <= Date_To)) On k Equals r.Room Into Group _
From r In Group.DefaultIfEmpty
Where r Is Nothing
Select k
```

How can I alter my design or expand on the current design to allow multiple rooms per booking? I'm a bit stumped!

Gracias de antemano!

## 3 Respuestas

1

What if you changed your initial query to simply search for rooms that are available on the person's arrival date, sorted by the longest amount of time each room is open for in descending order? If that amount of time is enough to cover the person's stay, then you're done. If it isn't, recurse. Query again to search for rooms that are available on the date the first room becomes unavailable, again sorted by the longest amount of time each room is open for in descending order. Continue until you've either hit a date that has no available rooms or you've found enough rooms to cover the person's stay.

For example, let's say you have someone who wants to book a reservation from 1/1 - 1/10 and there are three rooms with the following availability:

- Room 1: Available from 1/1 to 1/9
- Room 2: Available from 1/1 to 1/5
- Room 3: Available from 1/5 to 1/10

Your first query would be to see which rooms are available on 1/1, which would return rooms 1 and 2. However, since you're sorting by the longest amount of time each room is open for, your top result would be room 1. Your second query would be to see which rooms are available on 1/10 (the first date room 1 becomes unavailable), which would return room 3. You'd then determine that room 3 is open long enough to satisfy the person's reservation and you're done.

respondido 10 mar '12, 15:03

Thanks Kevin, I'll start testing out this logic to see how it fits! - tom

@Tom Did you ever get this to work? If so, please consider upvoting it and marking it as your selected answer. If not, I'd be interested in hearing about the solution you came up with. - Kevin Pang

0

Okay so in SQL:

Table room_booking is like `roomid INT (FK to room table), from DATE, to DATE`

so deciding IF there is enough room would be the question of the opposite: In the timeframe of the visit, is there a situation where there is NO ROOM available? So we split the frame in days (because rooms are not rented by the hour in your case, or are they?) and select that.

So you need to determinate every day for the visit PRIOR to the selection and then calculate how many free rooms you have for each of that days.

Luego esto:

```
SELECT count(roomid) - (SELECT count(id) from room) as numOfFreeRooms
FROM room_booking
WHERE '2012-03-10' >= from AND '2010-03-10' <= to
```

If any of the rows returns '0' (means all rooms are booked on that day) then you cannot fulfill your customers request.

If performance is relevant than this can be improved, but is more complicated then.

respondido 10 mar '12, 16:03

Angelo, I appreciate the effort but I think that's essentially the same as what my current code does. What I'm looking to do is extend the code to a scenario where a room isn't available for the entire duration of the from and to dates, so search for availability for multiple rooms for the same duration. - tom

@Tom The code i wrote does not care WHICH room is available it just cares about the question if there is ANY room available. So for a time period of 10 days that could be 10 different rooms as much as one the result would be the same. - Ángelo Fuchs

@Tom please be aware that you need to call that SQL for every day within the time period once, so for a 10 days visit you have to call this 10 times. - Ángelo Fuchs

Thanks Angelo, sorry I misunderstood your response. I think I can potentially use this approach but the one downside I can see is this might lead to one booking using more rooms than it needs to. I'd like to optimize the query so I book the least amount of rooms possible for the duration of the stay. I'll work it into my thinking, thanks! - tom

This seems suboptimal in that you will always run a query for every day of the person's stay. Not to mention that it doesn't try to minimize the number of room changes a person will have to go through. If I were a guest and I was told I'd be staying in 10 different rooms for my 10 night stay, I'd be pretty upset, especially if there was a room that was open for the entire 10 night span. - Kevin Pang

0

So my second solution, its (as said in the comments to the first one) quite complicated but I think its quite efficient as well.

I will not post code but rather the overall concept, if you are interested in specific details I'll see what I can do.

Problem: We create a abstraction where every room on every day is either available or blocked. We are interested in the available rooms in the time the guest wants to visit. We want to select the combination of rooms that need the least relocations of the guest.

Abstract: We create a two dimensional matrix of room/day combinations where every day is represented by a power of two (the DAYVALUE). A room thats available has the corresponding DAYVALUE. A room thats blocked as a value of SERO. So if we sum all DAYS for a ROOM we can determinate what COMBINATION of ROOMS fulfills the full time.

More specific: after we get the SUM of all VALUES for a ROOM we can use the binary OR function to decide if a given combination of rooms fullfills the complete stay by comparing the result of the OR operation with the SUM of values for all DAYS.

Note that the DAYVALUE is not stored in the dayTable. It is calculated for every request (2^(STARTDAY-DAY))

Hormigón:

1) You need to create a table that contains all DAYS. It has exactly ONE column that contains a date (no time, no timezone only the day). I would recommend it to contain ALL days from now until in a hundred years. (so you will have to populate it only once). (Note: This solves the problem that you cannot select every day once in a SQL Query)

2) You create a VIEW that produces an output like this:

```
DAY ; DAYVALUE ; ROOM1 ; ROOM2; ROOM3 ; ROOM4 ; ... ; ROOMn
20120313 ; 1 ; 0 ; 0; 1 ; 1 ; ... ;
20120314 ; 2 ; 2 ; 0; 2 ; 2 ; ... ;
20120315 ; 4 ; 4 ; 0; 0 ; 4 ; ... ;
20120316 ; 8 ; 8 ; 0; 0 ; 0 ; ... ;
20120317 ; 16 ; 16 ; 16; 16 ; 0 ; ... ;
```

3) Produce a SUM of this.

```
DAYVALUE ; ROOM1 ; ROOM2; ROOM3 ; ROOM4 ; ... ; ROOMn
31 ; 30 ; 16; 19 ; 7 ; ... ;
```

4) see if any single of the room values matches the sum of the DAYVALUE (and therefore is available all the time)

5) if 4 did not succeed create an OR value of every two of the results and compare it to the SUM of the DAYVALUE

```
ROOM1 OR ROOM2 = 30 <> 31
ROOM1 OR ROOM3 = 31 == 31. This is a valid match of rooms.
```

6) If none matched for two rooms you have to proceed this for 3 ROOMS and so on.

Using this procedure always produces the correct set of rooms that are available in the time of the visit and if you construct your database in the correct way (or have sufficiently low amount on rooms) the query should complete in a acceptable time.

Have fun (I had!)

respondido 16 mar '12, 06:03

There are ~36,500 days in 100 years. If each day is represented by a power of 2, the DAYVALUE could go up to 2^36,500. Representing this number takes 36,500 bits (~4.4 kilobytes) and that's just to represent whether 1 room is available for 1 day! If you want to store the availability for 1 room for all 36,500 days you're looking at 4.4 kb / day * 36,500 days = 160,600 kb (~156 megabytes). Multiply that by the number of rooms available and that's roughly how much space you need to store this data structure. - Kevin Pang

@KevinPang You totally misunderstood me. You shall save the 36500 days. Period. Nothing else. The other thing is a view you call for every request and not to be stored. - Ángelo Fuchs

I still don't understand then. You stated that every day is represented by its DAYVALUE, which is a power of two. If there are 36,500 days, then the maximum DAYVALUE will be 2^36,500, right? If so, then you need to think about the storage implications of using numbers that large. Let's say ROOM1 is available on all 36,500 days. The sum of its ROOMVALUES would be 1 + 2 + 4 + 8 + 16 + ... + 2^36,500. Is that correct? If so, you're going to need a lot of space to store all of these values and their sum. Processing time will be an issue as well. - Kevin Pang

@KevinPang AH! Now I see your problem. The DAYVALUE should start with 1 for every request and should be calculated in the view (2^(DAY-STARTDAY)), its not stored in the dayTable. I'll edit my answer to reflect that - Ángelo Fuchs

I don't see how that addresses the storage and performance issues I've described. In order to generate the view your database server is going to have to compute and store those incredibly large numbers. Note that while the DAYVALUEs aren't stored in a database table, that calculating them will still require the database server to store them in memory so that it can calculate the sums and compare them against the desired DAYVALUE sum. - Kevin Pang

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas .net sql database-design or haz tu propia pregunta.

I can't speak .net but I could code you this in SQL. would that help? - Angelo Fuchs

Angelo, I'd definitely be interested in seeing some SQL! - Tom

could you solve your problem? If yes how? And did any of the answers here help you? - Angelo Fuchs