Это не полный ответ, но он поможет вам на полпути:
SELECT o.openingStart, IFNULL(o.openingEnd, '2019-04-26 21:00:00') AS openingEnd
FROM (
SELECT r.endDateTime AS openingStart
, (SELECT r2.startDateTime
FROM reservations AS r2
WHERE r2.startDateTime > r.endDateTime
AND r2.endDateTime < '2019-04-27 00:00:00'
ORDER BY r2.startDateTime ASC
LIMIT 1
) AS openingEnd
FROM ( SELECT startDateTime, endDateTime
FROM reservations
WHERE startDateTime >= '2019-04-26 00:00:00'
AND endDateTime < '2019-04-27 00:00:00'
UNION
SELECT '2019-04-26 00:00:00', '2019-04-26 09:00:00'
) AS r
) AS o
После этого вы захотите отфильтровать только по отверстиям два часа или дольше, а затем, возможно, потребуется присоединиться к некоторой статической таблице часов, чтобы расширить большие отверстия в меньшие, которые они могут вместить.
IFNULL на самом деле может использоваться во внутреннем запросе, но я подумал, что это может быть немного понятнее.
Примечание. Все литеральные значения даты и времени должны быть заменены на соответствующие значения параметров.