Question

I have an accommodation booking engine, which follows these rules:

  • Users can book up to 7 rooms for any date.
  • Users must book only blocks of 2 days, 4 days and 6 days.
  • Users cannot book for Thursday (closed for cleaning).
  • Sometimes entire weeks will be unavailable due to corporate group bookings.

Here are some examples:

  • A 2 day block might be Friday and Saturday, Sunday and Monday or Tuesday and Wednesday.
  • A 4 day block might be Friday to Monday or Sunday to Wednesday.
  • A 6 day block might be from Friday to Wednesday.

The system has a simple table in the database that is a list of each date with the 7 rooms. The field for each room can be 0 for unavailable or 1 for available.

Table is called vg_booking_availability. Here is a snapshot.

vg_booking_availability database table snapshot

I need a way to search the table against a users search selection.

The might search as any combination of 2, 4 or days and between 1 and 7 rooms.

I'm not sure if the solution is to do a database lookup on all dates and all rooms, then creating a multi-dimensional array and cross checking with the user's search is the way to go forward. And if it is how I would do this?

Was it helpful?

Solution

Here is a way to do this in SQL, for just two-day bookings, for room_1:

SELECT
    avail1.date start_date,
    "room_1" room_name
FROM vg_booking_availability avail1
/* This row is the next day to the first one */
INNER JOIN vg_booking_availability avail2 ON (avail1.date + 1 = avail2.date)
WHERE
    avail1.room_1 = 0
    AND avail2.room_1 = 0
    /* Add in a clause to check future dates only here */
;

You could add all the rooms in this as bracketed OR statements, but I'd be inclined to run that as a separate query (otherwise you'd have to re-search your result in PHP to determine which room returned as available)

We are getting into a bit of trouble here because all the rooms are denormalised - they would be better in another table where they can be treated much more generically.

This example can be expanded by adding more aliased rows for 4-day and 7-day searches respectively. The unavailability of rooms on a Thursday (or whatever other rules) is not directly relevant to the problem, since you can just create future rows of availability (based on how far into the future people book) and then make rooms unavailable according to those rules. That's a separate (and trivial) problem.

I'd also be inclined to change this, so you use NULL as available and a foreign key to a customer table as unavailable. That will then give you useful information about why a room is unavailable, and will allow you to make it available again easily if a specific customer cancels their booking.

Lastly, this solution has the capacity for a large number of joins, and so testing this against data sets is essential. If you were to run this on a 10K row table it'd be fine, but it might not be if you have 1M rows (depending on your hardware and load, of course). So, once you have this working, I recommend you create a data generator (PHP is good for this) and ensure you can get the performance you require.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top