• If you don't want to create a calendar table, you can do this (which really just creates the calendar table on the fly).

    CREATE TABLE #Contracts

    (

    ContractNumber INT

    ,ContractStartDate DATETIME

    ,ContractEndDate DATETIME

    ,ContractAmount MONEY

    );

    INSERT INTO #Contracts

    VALUES (1234,'01-Jul-2012','30-Nov-2012',5000.00)

    ,(5678,'01-Jul-2012','30-jun-2013',12000.00)

    ;WITH StartMonth (sm, nm) AS (

    SELECT MIN(ContractStartDate)

    ,DATEDIFF(month, MIN(DATEADD(month, DATEDIFF(month, 0, ContractStartDate), 0))

    ,MAX(DATEADD(month, 1, DATEADD(month, DATEDIFF(month, 0, ContractEndDate), 0))-1))

    FROM #Contracts),

    Tally (n) AS (

    SELECT 0 UNION ALL

    SELECT TOP (SELECT nm FROM StartMonth) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))

    FROM (VALUES ($),($),($),($),($),($),($),($),($),($)) a(n)

    CROSS JOIN (VALUES ($),($),($),($),($),($),($),($),($),($)) b (n)),

    MyContracts AS (

    SELECT ContractNumber

    ,ContractMonth

    ,ContractAmount=CASE WHEN ContractStartDate > ContractMonth OR

    ContractEndDate < ContractMonth THEN 0

    ELSE ContractAmount/(DATEDIFF(month, ContractStartDate, ContractEndDate)+1) END

    FROM #Contracts a

    CROSS APPLY Tally b

    CROSS APPLY (SELECT ContractMonth=DATEADD(month, n, ContractStartDate)) c)

    SELECT ContractNumber

    ,[Jul]=MAX(CASE WHEN MONTH(ContractMonth) = 7 THEN ContractAmount END)

    ,[Aug]=MAX(CASE WHEN MONTH(ContractMonth) = 8 THEN ContractAmount END)

    ,[Sep]=MAX(CASE WHEN MONTH(ContractMonth) = 9 THEN ContractAmount END)

    ,[Oct]=MAX(CASE WHEN MONTH(ContractMonth) = 10 THEN ContractAmount END)

    ,[Nov]=MAX(CASE WHEN MONTH(ContractMonth) = 11 THEN ContractAmount END)

    ,[Dec]=MAX(CASE WHEN MONTH(ContractMonth) = 12 THEN ContractAmount END)

    ,[Jan]=MAX(CASE WHEN MONTH(ContractMonth) = 1 THEN ContractAmount END)

    ,[Feb]=MAX(CASE WHEN MONTH(ContractMonth) = 2 THEN ContractAmount END)

    ,[Mar]=MAX(CASE WHEN MONTH(ContractMonth) = 3 THEN ContractAmount END)

    ,[Apr]=MAX(CASE WHEN MONTH(ContractMonth) = 4 THEN ContractAmount END)

    ,[May]=MAX(CASE WHEN MONTH(ContractMonth) = 5 THEN ContractAmount END)

    ,[Jun]=MAX(CASE WHEN MONTH(ContractMonth) = 6 THEN ContractAmount END)

    FROM MyContracts

    GROUP BY ContractNumber

    DROP TABLE #Contracts

    If you have an unknown number of months, you'd need to convert this to Dynamic SQL, making the column headers something like [mmm-yy] and modifying the MONTH = test within the CASE accordingly.

    You might note how I have normalized the contract start dates to the first of the month and the contract end dates to the end of the month.


    My mantra: No loops! No CURSORs! No RBAR! Hoo-uh![/I]

    My thought question: Have you ever been told that your query runs too fast?

    My advice:
    INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
    The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.

    Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
    Since random numbers are too important to be left to chance, let's generate some![/url]
    Learn to understand recursive CTEs by example.[/url]
    [url url=http://www.sqlservercentral.com/articles/St