Here is one way to do it - probably not the most elegant or not the simplest (and not tested to boot!) Besides, as I was typing this, I had various questions, and I made assumptions in each case. But it compiles, the parser liked it :--)You have to have an ordering scheme, and I assumed ordereing by date.with OrderedCte as( select row_number() over (order by coalesce(inDates,outDates)) as rowId, * from YourTable)select a.inDates as PeriodStart, min(b.inDates) PeriodEndfrom OrderedCte a left join OrderedCte b on b.rowId >= a.rowId and exists (select * from OrderedCte c where c.rowId = b.rowId+1 and c.Indates is null)where (a.rowId = 1 or exists (select * from OrderedCte c where c.rowId=a.rowId-1 and c.Indates is null)) and a.inDates is not nullgroup by a.inDates