Click here to Skip to main content
15,902,840 members
Articles / Programming Languages / SQL
Article

Generate Date Table in SQL Server

Rate me:
Please Sign up or sign in to vote.
2.44/5 (6 votes)
1 Jun 2008CPOL 50.7K   13   7
Generate Date Table in SQL Server

Background

In many reports, one of the axis will be the a date range, either monthly or daily. However, there may be no data in a specific month or on a specific day. There will be no record when joining different tables. For example, if no user on 2008-05-03, the row of 2008-05-03 will not appear


DateNumber of User
2008-05-013
2008-05-025
2008-05-046

This SQL script generates a date range for left/right joining other tables so the result will include date with no data.

DateNumber of User
2008-05-013
2008-05-02
5
2008-05-030
2008-05-04
6
Create Function dbo.fnDateTable
(
  @StartDate datetime,
  @EndDate datetime,
  @DayPart char(5) -- support 'day','month','year','hour', default 'day'
)
Returns @Result Table
(
  [Date] datetime
)
As
Begin
  Declare @CurrentDate datetime
  Set @CurrentDate=@StartDate
  While @CurrentDate<=@EndDate
  Begin
    Insert Into @Result Values (@CurrentDate)
    Select @CurrentDate=
    Case
    When @DayPart='year' Then DateAdd(yy,1,@CurrentDate)
    When @DayPart='month' Then DateAdd(mm,1,@CurrentDate)
    When @DayPart='hour' Then DateAdd(hh,1,@CurrentDate)
    Else
      DateAdd(dd,1,@CurrentDate)
    End
  End
  Return
End

Points of Interest

Parameterized User-defined function is very useful. And caller to the function can use the result directly just like a table.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Hong Kong Hong Kong
A .NET Programmer for 8 years, who wants to share the experience.

Comments and Discussions

 
GeneralA more robust approach based on SQL Guru Jeff Moden's numbers table Pin
astanton19783-Jun-08 2:43
astanton19783-Jun-08 2:43 
From a post of Jeff Moden's that I read (cant find it at the moment). This first creates a temp table of numbers (using Jeff's identity trick), and then creates the table of dates based on that sequential numbers table. The whole operation takes about 2 seconds to generate 30 years of dates, which is a hundred times faster than the WHILE loop.

The only drawback is that since it uses temp tables, I don't think it can be included in a table function. This is not really a problem because both the sequential numbers and table of dates are VERY handy to have in any database, cost very little space, and perform much better than a dynamically generated list of dates (please trust me on this... I learned the hard way).

Here is the whole script...
/* Props to Jeff Moden for the sweet IDENTITY trick */

DECLARE @DaysFromGoLive int /*The date you want to start your dates on, in this case Jan 1, 2008*/
SET @DaysFromGoLive = (SELECT (DATEDIFF(dd,'01/01/2008',GETDATE()) + 1))

 SELECT TOP 10950 --30 years of days
        IDENTITY(INT,1,1) as N
   INTO #Numbers
   FROM Master.dbo.SysColumns sc1,
        Master.dbo.SysColumns sc2

CREATE TABLE [dbo].[TableOfDates](
	[fld_date] [datetime] NOT NULL,
 CONSTRAINT [PK_TableOfDates] PRIMARY KEY CLUSTERED 
(
	[fld_date] ASC
)WITH FILLFACTOR = 99 ON [PRIMARY]
) ON [PRIMARY]


INSERT INTO
      dbo.TableOfDates
SELECT 
      DATEADD(dd,nums.n - @DaysFromGoLive,CAST(FLOOR(CAST(GETDATE() as FLOAT)) as DateTime)) as FLD_Date
FROM #Numbers nums

SELECT MIN(FLD_Date) FROM dbo.TableOfDates
SELECT MAX(FLD_Date) FROM dbo.TableOfDates

DROP TABLE #Numbers



Also note the...
CAST(FLOOR(CAST(<your date=""> as FLOAT)) as DateTime)</your>
...this keeps the date time as numbers (chops off the time portion and converts it back to date), and performs better than the string comparisons (datepart = 'year'). When joining this table in, use this trick on the table you are joining to the TableOfDates, and add
AND MissingDataTable.DateColumn IS NULL
to the were clause so that the date is listed even if there is no data in the MissingDataTable.
GeneralRe: A more robust approach based on SQL Guru Jeff Moden's numbers table Pin
WPKF3-Jun-08 16:30
WPKF3-Jun-08 16:30 
GeneralRe: A more robust approach based on SQL Guru Jeff Moden's numbers table Pin
astanton19784-Jun-08 5:32
astanton19784-Jun-08 5:32 
GeneralRe: A more robust approach based on SQL Guru Jeff Moden's numbers table Pin
Jeff Moden13-Sep-09 15:50
Jeff Moden13-Sep-09 15:50 
GeneralVery large hammer Pin
Chris Maunder2-Jun-08 2:12
cofounderChris Maunder2-Jun-08 2:12 
GeneralRe: Very large hammer Pin
Member 14586602-Jun-08 3:13
Member 14586602-Jun-08 3:13 
GeneralRe: Very large hammer Pin
WPKF2-Jun-08 15:45
WPKF2-Jun-08 15:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.