SQL: Turn a Date Range into a List of Dates

I’m working on a project today that deals with date ranges being stored in SQL Server. Imagine a row in a table with a starting and an ending date. My desired output is to transform each single row into several, one for each date within the given date range.

Since I couldn’t find an example exactly like what I needed, I felt I should share what I came up with. I’ll let the code speak for itself. It uses a recursive Common Table Expression (CTE).

The caveats are: you have to run this on SQL Server 2005 or newer to use the WITH keyword, and if any individual date range is more than 100 days, you’ll get an error by default [you can use OPTION (MAXRECURSION value) to increase that limit]. UPDATE: I’ve added a WHERE clause to prevent the error related to the default recursion limit. This change will leave out date ranges larger than 100 days, which is fine for me because anything larger than two weeks would be a data entry error in my situation.

DECLARE @dateranges TABLE (range_id VARCHAR(2), date_begin DATETIME, date_end DATETIME)
INSERT @dateranges SELECT 'A', '2010-01-01', '2010-01-03'
INSERT @dateranges SELECT 'B', '2008-02-27', '2008-03-01'
INSERT @dateranges SELECT 'C', '2010-04-26', '2010-04-26'
INSERT @dateranges SELECT 'D', '2000-02-01', '2003-02-20'

;WITH cte (id, d)
     AS (SELECT tbl.range_id AS id
                ,tbl.date_begin AS d
           FROM @dateranges tbl
          WHERE DATEDIFF(DAY, tbl.date_begin, tbl.date_end) <= 100
         UNION ALL
         SELECT tbl.range_id AS id
                ,DATEADD(DAY, 1, cte.d) AS d
           FROM cte
                INNER JOIN @dateranges tbl
                  ON cte.id = tbl.range_id
          WHERE cte.d < tbl.date_end)
SELECT id AS range_id
       ,d AS date_within_range
  FROM cte
 ORDER BY id, d

You start with this:

range_id date_begin date_end
A 2010-01-01 2010-01-03
B 2008-02-27 2008-03-01
C 2010-04-26 2010-04-26
D 2000-02-01 2003-02-20

and end up with this:

range_id date_within_range
A 2010-01-01
A 2010-01-02
A 2010-01-03
B 2008-02-27
B 2008-02-28
B 2008-02-29
B 2008-03-01
C 2010-04-26

Notice that “D” is filtered out of these results.

Programming , ,
  • Sherry

    Thanks a lot, that’s what I want

  • Pablo

    Thank you!