Я прошу прощения за то, что немного устала от такого запроса, и я не могу гарантировать, что я правильно понял весь синтаксис, но я думаю, что что-то вроде следующего может работать:
SELECT id, DATE_ADD(b.booking_date, INTERVAL (end_date + 1 DAY) as date
FROM (
SELECT r.id, STR_TO_DATE('2016-01-01', '%Y-%m-%d') as start_of_month, b.booking_date as start_date, DATE_ADD(b.booking_date, INTERVAL (nights - 1) DAY) as end_date
FROM room r
LEFT JOIN booking b ON r.id = b.room_no
ORDER BY r.id, b.booking_date
) as room_bookings
WHERE DATE_DIFF(room_bookings.start_of_month, room_bookings.start_date) >= 3
OR DATE_DIFF(room_bookings.end_date, (
SELECT b2.booking_date FROM booking b2
WHERE b2.room_no = room_bookings.id AND b2.booking_date > room_bookings.start_date
ORDER BY b2.booking_date LIMIT 1)
) >= 3
На самом деле, теперь, когда я набираю все это, вы можете настроить WHERE основного запроса, чтобы вам даже не понадобился подвыбор room_bookings. Надеюсь, это поможет и не слишком далеко от цели.