• Samuel Vella (2/26/2009)


    mh, your solution is fine but when you test it with a lot of data against a cursor, the cursor is orders of magnitude faster

    Man, you have absolutely the correct idea... you put your money where your mouth was with code! Well done!

    Just to share a few tricks with someone who actually tests code for performance, here's your test code generator...

    drop table sales

    CREATE TABLE Sales (DayCount smallint, channel varchar(50), Sales money)

    CREATE CLUSTERED INDEX ndx_DayCount ON Sales(DayCount)

    go

    SET NOCOUNT ON

    DECLARE @DayCount smallint, @Sales money, @channel varchar(50)

    SET @DayCount = 0

    SET @Sales = 10

    set @channel = 'a'

    WHILE @DayCount < 10000

    BEGIN

    INSERT Sales VALUES (@DayCount,@channel, @Sales)

    SET @DayCount = @DayCount + 1

    SET @Sales = @Sales + 15

    set @channel = case

    when right(cast(@daycount as varchar), 1) = 0 then 'a'

    when right(cast(@daycount as varchar), 1) = 1 then 'b'

    when right(cast(@daycount as varchar), 1) = 2 then 'c'

    when right(cast(@daycount as varchar), 1) = 3 then 'd'

    when right(cast(@daycount as varchar), 1) = 4 then 'e'

    when right(cast(@daycount as varchar), 1) = 5 then 'f'

    when right(cast(@daycount as varchar), 1) = 6 then 'g'

    when right(cast(@daycount as varchar), 1) = 7 then 'h'

    when right(cast(@daycount as varchar), 1) = 8 then 'i'

    when right(cast(@daycount as varchar), 1) = 9 then 'j'

    end

    END

    It does a fine job of making 10,000 rows in somewhere just over 3 seconds on my 6 year old box... but, what if you wanted a million rows of that same example just to make sure? The following code makes the same kind of data example, but it makes 100 times more rows in only about 4-5 seconds more...

    --===== Conditionaly drop the test table

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

    DROP TABLE #Sales

    --===== Populate the table with a million rows of data similar to yours.

    -- This ISNULL is to make the resulting DayCount column NOT NULL so

    -- we can put a primary key on it later.

    SELECT TOP 1000000

    ISNULL(CAST(ROW_NUMBER() OVER (ORDER BY sc1.ID) - 1 AS INT),0) AS DayCount,

    CAST(ROW_NUMBER() OVER (ORDER BY sc1.ID) *15 AS MONEY) AS Sales,

    CHAR(CAST(ROW_NUMBER() OVER (ORDER BY sc1.ID) - 1 AS INT)%10+ASCII('a')) AS Channel

    INTO dbo.#Sales

    FROM Master.sys.SysColumns sc1

    CROSS JOIN Master.sys.SysColumns sc2

    --===== Add the primary key

    -- I don't name these on temp tables because they must be unique.

    ALTER TABLE dbo.#Sales

    ADD PRIMARY KEY CLUSTERED (DayCount)

    Like I said, well done on the testing... now you have a way to do some really heavy duty testing that no one will be able to argue with.

    --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)