Это интересный вопрос.
Для заданной даты , давайте рассмотрим перекрытия (я ввел все свои даты, как у вас, но для 01.01.2011):
SELECT dt1.StartTime AS StartOverlap,
CASE
WHEN dt1.EndTime > dt2.EndTime THEN dt1.EndTime
ELSE dt2.EndTime
END AS EndOverlap
FROM datetimetest dt1, datetimetest dt2
WHERE dt2.StartTime > dt1.StartTime
AND dt2.StartTime < dt1.EndTime
Это дает мне:
StartOverlap EndOverlap
01/01/2011 08:15:00 01/01/2011 08:55:00
01/01/2011 14:00:00 01/01/2011 14:45:00
Отлично, теперь мы знаем время начала и окончания, когда мы не можем использовать это перекрытие.
Как мы можем получить другие не перекрывающиеся времена?
Я бы посмотрел на все периоды времени, которые находятся в перекрывающихся диапазонах, а затем выбрал идентификаторы, которые не находятся в этом диапазоне дат:
SELECT id
FROM (SELECT dt1.StartTime AS StartOverlap,
CASE
WHEN dt1.EndTime > dt2.EndTime THEN dt1.EndTime
ELSE dt2.EndTime
END AS EndOverlap
FROM datetimetest dt1, datetimetest dt2
WHERE dt2.StartTime > dt1.StartTime
AND dt2.StartTime < dt1.EndTime
) AS Overlaps, datetimetest dtt
WHERE dtt.StartTime >= Overlaps.StartOverlap
AND dtt.EndTime <= Overlaps.EndOverlap
Это дает мне список всех идентификаторов, которые находятся в перекрытиях. Затем я просто выбираю все записи, которые НЕ находятся в перекрытиях:
SELECT StartTime, EndTime FROM datetimetest
WHERE id NOT IN(
SELECT id
FROM (SELECT dt1.StartTime AS StartOverlap,
CASE
WHEN dt1.EndTime > dt2.EndTime THEN dt1.EndTime
ELSE dt2.EndTime
END AS EndOverlap
FROM datetimetest dt1, datetimetest dt2
WHERE dt2.StartTime > dt1.StartTime
AND dt2.StartTime < dt1.EndTime
) AS Overlaps, datetimetest dtt
WHERE dtt.StartTime >= Overlaps.StartOverlap
AND dtt.EndTime <= Overlaps.EndOverlap)
Чтобы дать мне:
StartTime EndTime
01/01/2011 12:30:00 01/01/2011 13:15:00
Затем я могу объединить оба запроса, чтобы получить список всех используемых временных интервалов.
Поскольку мы фактически перекрестно соединяем одну и ту же таблицу, я бы добавил к каждому запросу дополнительное предложение, чтобы ограничить дату одной датой.