SQL and the like

Dave Ballantyne's blog. Freelance SQL Server database designer and developer at Clear Sky SQL

Returning a chain of events with a recursive CTE

This is a question that cropped up SQLServerCentral.
Imagine you have a list of dates, for which you need to know the next day after a specified interval. 

So in this list you want to return those with an interval of 3Days (ie those in Red)
01Jan
02Jan
07jan
11Jan
12Jan
28jan
 
To add further complication there are also multiple ranges.  Heres some sample data
drop table #DateSteps
go
Create table
#DateSteps
(
Handler integer,
EventDate smalldatetime
)
go
Create unique index
idxDateSteps on #DateSteps(handler,EventDate)
go
insert into
#dateSteps values(1,'01jan1990')
insert into #dateSteps values(1,'07jan1990')
insert into #dateSteps values(1,'11jan1990')
insert into #dateSteps values(1,'12jan1990')
insert into #dateSteps values(1,'28jan1990')
insert into #dateSteps values(1,'08mar1990')
insert into #dateSteps values(2,'02jan1990')
insert into #dateSteps values(2,'04jan1990')
insert into #dateSteps values(2,'10jan1990')
insert into #dateSteps values(2,'12jan1990')
insert into #dateSteps values(2,'15mar1990')

The key to this routine is the use of row_number() within the derived table at the recursive element of the CTE.  This enables us to return only the next row that is three days or more after the input date.
with cteStartDates(Handler,EventDate)
as
(
Select Handler,
min(EventDate)
from #datesteps
group by Handler
),
CteRecursiveSkip(Handler,EventDate)
as
(
Select Handler,EventDate
from cteStartDates
union all
Select x.Handler,x.EventDate
from (
Select #datesteps.Handler,#datesteps.EventDate,
RowNum = row_number()
over (partition by #datesteps.Handler
order by #datesteps.EventDate)
from CteRecursiveSkip
join #datesteps
on #datesteps.Handler = CteRecursiveSkip.Handler
and #datesteps.Eventdate >= CteRecursiveSkip.EventDate+3
) as x
where x.RowNum = 1
)
Select *
from CteRecursiveSkip
order by Handler,EventDate
Yet another cursor resigned to the garbage can.  Performance should also be quite good across large datasets.

Comments

No Comments