0

We have this database schema to work with: http://sqlzoo.net/wiki/Guest_House

The issue is a common request as such:
A customer wants a double room for 7 consecutive nights at some time between a starting date and an ending date

The output should be like this:

+-----+------------+
| id  | MIN(i)     |
+-----+------------+
| 210 | 2016-11-19 |
| 304 | 2016-11-19 |
+-----+------------+

The way we approached the problem is to try and do a diff. Simply to take the difference between booking date of next instance with checkout date of previous instance. The difficulty is to define which two pairs make the previous-next pair, because when you are doing a cross self-join you are taking all the possible pairs!
We are aware that the way to treat such cases is to use depended subqueries such as here: https://stackoverflow.com/a/35615532/720484

However following this approach we ended up with a huge subquery as shown in this sql script:

select b1.room_no, ADDDATE(b2.booking_date, b2.nights) as date_avail
from
(select booking_id, booking_date, room_no, nights from booking where room_type_requested = 'double') as b1 INNER JOIN 
(select booking_id, booking_date, room_no, nights from booking where room_type_requested = 'double') as b2
ON b1.booking_id <> b2.booking_id and b1.room_no = b2.room_no
where b1.booking_date >= ADDDATE(b2.booking_date, b2.nights)
and DATEDIFF(b1.booking_date, b2.booking_date) = (
  select MIN(DATEDIFF(bi1.booking_date, bi2.booking_date)) as min_date_dist
  from
  (select booking_id, booking_date, room_no, nights from booking where room_type_requested = 'double') as bi1 INNER 
  JOIN 
  (select booking_id, booking_date, room_no, nights from booking where room_type_requested = 'double') as bi2
  ON bi1.booking_id <> bi2.booking_id and bi1.room_no = bi2.room_no
  where bi1.booking_date >= ADDDATE(bi2.booking_date, bi2.nights)
  and bi1.booking_id = b1.booking_id
  group by bi1.booking_id
)
and b1.booking_date - ADDDATE(b2.booking_date, b2.nights) >= 7 /* nights avail */
and ADDDATE(b2.booking_date, b2.nights) between '2016-11-03' and '2016-12-19'
order by date_avail, b1.room_no

How could you write this script more elegantly?

Rick James
  • 135,179
  • 13
  • 127
  • 222
George Pligoropoulos
  • 2,919
  • 3
  • 33
  • 65
  • well in Mariadb you could at least use common table expressions to help avoid some query repetition... what version are you using? – Paul Maxwell Dec 10 '17 at 00:38
  • Efficient "groupwise-max" algorithms can be found in http://mysql.rjweb.org/doc.php/groupwise_max – Rick James Dec 10 '17 at 18:29

0 Answers0