Следната заявка намира периодите в данните според вашата дефиниция. Първо използва корелирани подзаявки, за да определи дали даден запис е началото на период (тоест, няма припокриване с по-ранни периоди от време). След това присвоява "periodStart" като най-новото начало, което е началото на период без припокриване.
Следната (непроверена) заявка използва този подход:
with TimeWithOverlap as (
select t.*,
(case when exists (select * from dbo.Available tbefore where t.availStart > tbefore.availStart and tbefore.availEnd >= t.availStart)
then 0
else 1
end) as IsPeriodStart
from dbo.Available t
),
TimeWithPeriodStart as (
select two.*,
(select MAX(two1.AvailStart) from TimeWithOverlap two1 where IsPeriodStart = 1 and two1.AvailStart <= two.AvailStart
) as periodStart
from TimeWithOverlap two
)
select periodStart, MAX(AvailEnd) as periodEnd
from TimeWithPeriodStart twps
group by periodStart;
http://sqlfiddle.com/#!6/3483c/20 (Втора заявка)
Ако двата периода започват по едно и също време, това все още работи, тъй като стойностите на AvailStart са еднакви. Поради корелираните подзаявки, това може да не се представи много добре дори при средно големи набори от данни.
Има и други методи за подход към това. Например, ако имате SQL Server 2012, ще можете да използвате функции за кумулативна сума, които предлагат по-прост метод.