Sprocs to create Date and Time Dimensions

Working a project and needed generic date and time dimensions, wrote the following stored procedures, blogged here for future use…

 

The date one accepts 2 parameters a start date and an end date, it then creates a row for each day between these dates.

 

We had a bit of a discussion on the time one about whether it should go to the minute or second level so I’ve included a parameter called @grain which should be set to either ‘second’ or ‘minute’, so you can choose which level you need.

 

SEE COMMENTS FOR TIME DIMENSION SPROC…

 

USE[DanDev]

GO

/****** Object: StoredProcedure [dbo].[PopulateDimDate] Script Date: 05/19/2010 17:13:24 ******/

SETANSI_NULLSON

GO

SETQUOTED_IDENTIFIERON

GO

CREATEprocedure [dbo].[PopulateDimDate] (@start asdatetime, @end asdatetime)

as

declare @dte asdatetime

— run the below statement to test

— exec PopulateDimDate ’01 Jan 2000′, ’31 Dec 2049′

— 150 years worth takes 22 seconds to create 54,787 rows

— either create or truncate the table

ifobject_id(‘DimDate’)isnull

begin

CREATE TABLE [dbo].[DimDate]

(

[DateKey] [int] NULL,

[CalDate] [datetime] NULL,

[TextDateShort] [nvarchar](6) NULL,

[TextDateLong] [nvarchar](11) NULL,

[CalWeek] [int] NULL,

[CalMonthNum] [int] NULL,

[CalQtr] [int] NULL,

[CalYear] [int] NULL,

[IsWeekend] [bit] NULL,

[DoW] [nvarchar](9) NULL,

[DoM] [int] NULL,

[CalMonthName] [nvarchar](9) NULL,

[IsFirstDayOfMonth] [bit] NULL,

[IsLastDayOfMonth] [bit] NULL,

[IsLeapYear] [bit] NULL

)

end

else

truncate table dbo.DimDate

— use while to create all rows with just date field populated to keep it quick as poss

set @dte = @start

while @dte <= @end

begin

insert into DimDate (CalDate) values (@dte)

set @dte = dateadd(dd,1,@dte)

end

— Now populate all additional fields

update DimDate

set DateKey = year(CalDate)*10000+month(CalDate)*100+day(CalDate),

TextDateShort = left(convert(varchar(16),CalDate,113),6),

TextDateLong = left(convert(varchar(16),CalDate,113),11),

CalWeek = datepart(week,CalDate),

CalMonthNum = month(CalDate),

CalQtr = (month(CalDate)/4)+1,

CalYear = year(CalDate),

IsWeekend = case when datename(dw,CalDate) in(‘Saturday’,‘Sunday’) then ‘TRUE’ else ‘FALSE’ end,

DoW = datename(dw,CalDate),

DoM = day(CalDate),

CalMonthName = datename(month,CalDate),

IsFirstDayOfMonth = case when day(CalDate) = 1 then ‘TRUE’ else ‘FALSE’ end,

IsLastDayOfMonth = case when day(dateadd(dd,1,CalDate)) = 1 then ‘TRUE’ else ‘FALSE’ end,

IsLeapYear = case when year(CalDate) % 4 = 0

and (year(CalDate) % 100 <> 0

or year(CalDate) % 400 = 0) then ‘TRUE’ else ‘FALSE’ end

Unknown's avatarAbout Dan Wakefield
BI / Data Warehouse Developer

One Response to Sprocs to create Date and Time Dimensions

  1. Unknown's avatar Dan says:

    USE [DanDev]GO/****** Object: StoredProcedure [dbo].[PopulateDimTime] Script Date: 05/19/2010 17:13:52 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE procedure [dbo].[PopulateDimTime] (@grain as varchar(6))as– @grain is either \’minute\’ or \’second\’declare @time datetime– test– exec PopulateDimTime \’turd\’– 20 seconds to create at second grain, less than a second at minute grainif @grain not in(\’second\’,\’minute\’)beginprint \’Please enter second or minute in @grain parameter\’returnendif @grain = \’second\’begin– either create or truncate the table– if prev created at only minute level then need to drop and recreateif not exists (select * from INFORMATION_SCHEMA.COLUMNSwhere TABLE_NAME = \’DimTime\’ and COLUMN_NAME = \’NumSecond\’)if object_id(\’DimTime\’) is null drop table DimTimeif object_id(\’DimTime\’) is nullbeginCREATE TABLE DimTime(TimeKey int NULL,TimeValue datetime NULL,TextTime nchar(8) NULL,Intraday nchar(5) NULL,AmPm nchar(2) NULL,TextHour nchar(2) NULL,TextMinute nchar(2) NULL,TextSecond nchar(2) NULL,NumHour int NULL,NumMinute int NULL,NumSecond int NULL)endelsetruncate table DimTimeset @time = \’00:00:00\’– use while to create all rows with just date field populated to keep it quick as posswhile @time <= \’23:59:59\’begininsert into DimTime (TimeValue) values (@time)set @time = dateadd(second,1,@time)end– Now populate all additional fieldsupdate DimTimeset TimeKey = datepart(hour,TimeValue)*10000+datepart(minute,TimeValue)*100+datepart(second,TimeValue),TextTime = convert(varchar(8),TimeValue,114),Intraday = replace(convert(varchar(2),TimeValue,114)+\’:\’+cast(datepart(minute,TimeValue)/15*15 as char(2)),\’:0\’,\’:00\’),AmPm = case when datepart(hour,TimeValue) < 12 then \’Am\’ else \’Pm\’ end,TextHour = convert(varchar(2),TimeValue,114),TextMinute = substring(convert(varchar(8),TimeValue,114),4,2),TextSecond = right(convert(varchar(8),TimeValue,114),2),NumHour = datepart(hour,TimeValue),NumMinute = datepart(minute,TimeValue),NumSecond = datepart(second,TimeValue)end — end of \’second\’ grain processingelsebegin– either create or truncate the table– if prev created at second level then need to drop and recreateif exists (select * from INFORMATION_SCHEMA.COLUMNSwhere TABLE_NAME = \’DimTime\’ and COLUMN_NAME = \’NumSecond\’)if object_id(\’DimTime\’) is null drop table DimTimeif object_id(\’DimTime\’) is nullbeginCREATE TABLE DimTime(TimeKey int NULL,TimeValue datetime NULL,TextTime nchar(5) NULL,Intraday nchar(5) NULL,AmPm nchar(2) NULL,TextHour nchar(2) NULL,TextMinute nchar(2) NULL,NumHour int NULL,NumMinute int NULL)endelsetruncate table DimTimeset @time = \’00:00:00\’– use while to create all rows with just date field populated to keep it quick as posswhile @time <= \’23:59:59\’begininsert into DimTime (TimeValue) values (@time)set @time = dateadd(minute,1,@time)end– Now populate all additional fieldsupdate DimTimeset TimeKey = datepart(hour,TimeValue)*10000+datepart(minute,TimeValue)*100+datepart(second,TimeValue),TextTime = convert(varchar(5),TimeValue,114),Intraday = replace(convert(varchar(2),TimeValue,114)+\’:\’+cast(datepart(minute,TimeValue)/15*15 as char(2)),\’:0\’,\’:00\’),AmPm = case when datepart(hour,TimeValue) < 12 then \’Am\’ else \’Pm\’ end,TextHour = convert(varchar(2),TimeValue,114),TextMinute = substring(convert(varchar(5),TimeValue,114),4,2),NumHour = datepart(hour,TimeValue),NumMinute = datepart(minute,TimeValue)end — end of \’minute\’ grain processing

Leave a comment