Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Data Management

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

    Search

    XML Feeds

    Google Ads

    « Do not disable foreign keysSQLUG.be meeting: Automating SSRS Deployments »
    comments

    Most of the scripts I've used to populate date dimension uses a cursor. Since data is loaded only once to a date dimension in the ETL life cycle, using a cursor isn't a sin.

    Still, when I was reviewing my own code the other day, I wanted to get rid of the cursor. Why not, Right?

    Here is a script that uses CTE and Window Functions to populate the date dimension.

    1. DECLARE @startdate DATE = '20000101'
    2.     , @enddate DATE = '20301231' ;
    3.  
    4. WITH c
    5. AS (
    6.     SELECT  Num = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
    7.     FROM sys.columns c
    8.     CROSS JOIN sys.columns c1
    9.     )
    10. , d
    11. AS (
    12.     SELECT  [date] = DATEADD(day, Num, @startdate)
    13.             , Num
    14.     FROM c
    15.     WHERE Num >= 0
    16.         AND Num <= DATEDIFF(day, @startdate, @enddate)
    17.     )
    18. SELECT datekey = CAST(CONVERT(VARCHAR(8), DATEADD(day, Num, @startdate), 112) AS INT)
    19.     , [date]
    20.     , [DayOfMonth] = DATEPART(day, [Date])
    21.     , [DayName] = DATENAME(weekday, [Date])
    22.     , [DayOfYear] = DATEPART(dayofyear, [Date])
    23.     , [WeekOfYear] = DATEPART(week, [Date])
    24.     , [MonthName] = DATENAME(month, [Date])
    25.     , [MonthNumber] = DATEPART(month, [Date])
    26.     , [QuarterNumber] = DATEPART(quarter, [Date])
    27.     , [Year] = YEAR([date])
    28.     , [FiscalYear] = CASE
    29.         WHEN DATEPART(month, [Date]) < 7
    30.             THEN YEAR([date])
    31.         ELSE YEAR([date]) + 1
    32.         END
    33. --Add more columns as needed.
    34. FROM d

    Let's take a closer look:

    1. Variables StartDate and EndDate hold the date range for the result set.
    2. We define a CTE (called c) that uses Row_Number() function to generate numbers starting from zero for each row in sys.columns. sys.columns is cross joined to itself to generate more number of [input] rows.
    3. We define another CTE (called d) that uses numbers from c, filters on date range, and converts numbers to dates based on the date variables.
    4. Finally, the Select statement uses Num and Date column aliases created by the two CTEs and date functions to create additional fields for the date dimension.

    You'll notice that the script doesn't have all columns a date dimension typically has. Don't call me lazy for that - it provides the logic and skeleton to add more columns. Just add them as needed.

    About the Author

    Samuel Vanga is a SQL Server Data Warehouse and Business Intelligence developer, and a LessThanDot.com blogger. Sam specializes in data integration using SQL Server Integration Services and building end-to-end business intelligence solutions. He also holds a MS degree in Computer Science.
    Social SitingsTwitterLinkedInLTD RSS Feed
    1874 views
    InstapaperVote on HN

    No feedback yet

    Leave a comment


    Your email address will not be revealed on this site.

    To mislead the spambots.

    Your URL will be displayed.
    (Line breaks become <br />)
    (Name, email & website)
    (Allow users to contact you through a message form (your email will not be revealed.)