• rka (9/3/2012)


    Has anyone done any similar SQL Script to generate this?

    Quite possibly thousands of times. 😀

    The first thing you need is the Swiss Army Knife for T-SQL known as a Tally Table. It has hundreds of uses and this is one of them. Please see the following article for what a Tally Table is and how it can be used to replace certain WHILE loops with incredible performance.

    http://www.sqlservercentral.com/articles/T-SQL/62867/

    Here's how to build a "unit based" Tally Table.

    --===== Do this in a nice safe place that everyone has

    -- (You can build a permanent one in any database)

    USE TempDB;

    IF OBJECT_ID('TempDB..Tally','U') IS NOT NULL

    DROP TABLE Tally;

    GO

    --===================================================================

    -- Create a Tally table from 1 to 11000

    --===================================================================

    --===== Create and populate the Tally table on the fly.

    SELECT TOP 11000

    IDENTITY(INT,1,1) AS N

    INTO dbo.Tally

    FROM Master.sys.ALL_Columns ac1

    CROSS JOIN Master.sys.ALL_Columns ac2

    ;

    --===== Add a CLUSTERED Primary Key to maximize performance

    ALTER TABLE dbo.Tally

    ADD CONSTRAINT PK_Tally_N

    PRIMARY KEY CLUSTERED (N) WITH FILLFACTOR = 100

    ;

    --===== Allow the general public to use it

    GRANT SELECT ON dbo.Tally TO PUBLIC

    ;

    GO

    After that, the Tally Table makes your problem easy to solve with a little help from some date/time functions and a CROSS JOIN...

    --===== Conditionally drop the test table to make reruns in SSMS easier.

    -- This is just a test table and is not a part of the solution.

    IF OBJECT_ID('tempdb..#YourTable','U') IS NOT NULL

    DROP TABLE #YourTable

    ;

    --===== Create the test table.

    -- This is just a test table and is not a part of the solution.

    CREATE TABLE #YourTable

    (

    YearMonth INT,

    [Value] INT

    )

    ;

    --===== Populate the table with test data.

    -- This is just test data and is not a part of the solution.

    INSERT INTO #YourTable

    (YearMonth,[Value])

    SELECT 201207,5000 UNION ALL

    SELECT 201208,4000 UNION ALL

    SELECT 201201,3100 UNION ALL

    SELECT 200002,2900

    ;

    --===== Solve the problem.

    SELECT YearMonth,

    [Day] = CONVERT(CHAR(10),DATEADD(mm,((YearMonth/100)-1900)*12 + YearMonth%100-1,0)+(t.N-1),103),

    [Value] = ([Value]+0.0)/DAY(DATEADD(mm,((YearMonth/100)-1900)*12 + YearMonth%100,0)-1)

    FROM #YourTable

    CROSS JOIN dbo.Tally t

    WHERE t.N <= DAY(DATEADD(mm,((YearMonth/100)-1900)*12 + YearMonth%100,0)-1)

    ORDER BY YearMonth, t.N

    ;

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)