Quantcast
Channel: Development
Viewing all articles
Browse latest Browse all 10

Using a Common Table Expression (CTE) to Generate a Date Range

$
0
0
There are times when you date reliant data that has gaps in it but you need a query that includes days even where data is missing. The data source may be a sales table where there may be days that no sales where made but you want to generate a calendar like cross-tab query for every day in a period. When I was asked by a colleague to help him with a similar problem it struck me that we could leverage a SQL 2005 CTE in a user defined function to act as a date range source for the query on which we could left join and fill in the missing days.

The solution is quite simple, all you need is a CTE that starts and the start date and recursively joins on to itself using DATEADD plus a day until it reaches the end date. Here is the function that I wrote:

CREATE FUNCTION GetDateRange 
(
    @StartDate 
DateTime
    @EndDate 
DateTime
)
RETURNS @DateRangeList 
TABLE 
(
    Date 
DateTime NOT NULL
)
AS 
BEGIN
    IF 
@StartDate > @EndDate
    
BEGIN
        
--Unfortunately you cannot raise an error in a UDF so simply return no rows
        
RETURN
    END;

    WITH 
DateRange(Date) AS
    
(
        
SELECT
            
@StartDate Date
        
UNION ALL
        SELECT
            DATEADD
(day, 1, Date) Date
        
FROM
            
DateRange
        
WHERE
            
Date < @EndDate
    )

    
INSERT @DateRangeList
    
SELECT Date 
    
FROM DateRange
    
--You could remove Maximum Recursion level constraint by specifying a MaxRecusion of zero
    
OPTION (MaxRecursion 10000);

    RETURN

END;

The performance of the query is pretty good, but is almost identical to using a temp table/table variable and a loop to generate the same data. On my P4 2.8GHZ machine at home both approaches generate a month's worth of days in 16ms and a year's worth in 30ms. I have to say I was somewhat surprised to find this out since I expected it to be faster but I suppose the inserts into the table variable negate the possible speed up. Regardless it is an interesting approach that I thought I'd share with you.

Viewing all articles
Browse latest Browse all 10

Trending Articles