Insert sequence number

  • ChrisM@home (7/22/2014)


    @wBob, you might find a TOP() -limited IBG-style inline tally even more efficient.

    Sort of like this:

    IF OBJECT_ID('dbo.numbers') IS NULL

    BEGIN

    CREATE TABLE dbo.numbers ( x INT, CONSTRAINT PK_numbers PRIMARY KEY ( x ) );

    WITH e1(n) as (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),

    e2(n) as (SELECT 1 FROM e1 a CROSS JOIN e1 b),

    e4(n) as (SELECT 1 FROM e2 a CROSS JOIN e2 b),

    eTally(n) as (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)))

    INSERT INTO dbo.numbers ( x )

    SELECT TOP 1000 n

    FROM eTally;

    END

    You may want to compare the actual execution plans between your code and this code.

  • Thank you for help.

    From "20-(MAX([sequence number])%20)" I got an idea.

    Finally, I use while loop to complete it.

  • That's a shame about the WHILE loop. I would encourage you to use one of the set-based options presented for you as they will scale much better.

    How many claims do you have to process?

  • Lynn Pettis (7/22/2014)


    ChrisM@home (7/22/2014)


    @wBob, you might find a TOP() -limited IBG-style inline tally even more efficient.

    Sort of like this:

    IF OBJECT_ID('dbo.numbers') IS NULL

    BEGIN

    CREATE TABLE dbo.numbers ( x INT, CONSTRAINT PK_numbers PRIMARY KEY ( x ) );

    WITH e1(n) as (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),

    e2(n) as (SELECT 1 FROM e1 a CROSS JOIN e1 b),

    e4(n) as (SELECT 1 FROM e2 a CROSS JOIN e2 b),

    eTally(n) as (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)))

    INSERT INTO dbo.numbers ( x )

    SELECT TOP 1000 n

    FROM eTally;

    END

    You may want to compare the actual execution plans between your code and this code.

    Almost. I meant inline as in the tally table is built on-the-fly:

    -- Demonstrate a solution using the sample data

    WITH

    e1(n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) dt (n)),

    e2(n) AS (SELECT 1 FROM e1 a CROSS JOIN e1 b),

    e4(n) AS (SELECT 1 FROM e2 a CROSS JOIN e2 b)

    SELECT

    d.[Claim number],

    [sequence number] = d.LastSequenceNumber + x.n

    FROM (

    SELECT

    [Claim number],

    RowsToConstruct = 20-(MAX([sequence number])%20),

    LastSequenceNumber = MAX([sequence number])

    FROM #SampleTable

    GROUP BY [Claim number]

    ) d

    CROSS APPLY (

    SELECT TOP (RowsToConstruct)

    n = ROW_NUMBER() OVER (ORDER BY (SELECT NULL))

    FROM e4

    ) x

    No more rows are constructed than are needed.

    “Write the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • I did trial that and honestly there is not a lot in it, with solution 1 (mine) slightly faster 5-10% on average at scale of 1 million. My test rig:

    ------------------------------------------------------------------------------------------------

    -- Setup START

    -- http://www.sqlservercentral.com/Forums/Topic1594823-2799-2.aspx?Update=1

    ------------------------------------------------------------------------------------------------

    USE tempdb

    GO

    IF OBJECT_ID('#claims') IS NOT NULL DROP TABLE #claims

    CREATE TABLE #claims

    (

    claimNumberINT,

    maxSequenceINT,

    PRIMARY KEY ( claimNumber, maxSequence )

    )

    GO

    ;WITH cte AS

    (

    SELECT TOP 1000000 ROW_NUMBER() OVER ( ORDER BY ( SELECT 1 ) ) rn

    FROM master.sys.columns c1

    CROSS JOIN master.sys.columns c2

    CROSS JOIN master.sys.columns c3

    )

    INSERT INTO #claims ( claimNumber, maxSequence )

    --VALUES ( 111, 17 ), ( 222, 38 ), ( 333, 20 )

    SELECT rn, rn % 33

    FROM cte

    GO

    IF OBJECT_ID('dbo.numbers') IS NULL

    BEGIN

    CREATE TABLE dbo.numbers ( x INT, CONSTRAINT PK_numbers PRIMARY KEY ( x ) )

    INSERT INTO dbo.numbers ( x )

    SELECT TOP 1000 ROW_NUMBER() OVER ( ORDER BY ( SELECT 1 ) ) x

    FROM master.sys.columns c1

    CROSS JOIN master.sys.columns c2

    CROSS JOIN master.sys.columns c3

    END

    GO

    ------------------------------------------------------------------------------------------------

    -- Solution 1 START

    ------------------------------------------------------------------------------------------------

    DBCC DROPCLEANBUFFERS

    DBCC FREEPROCCACHE

    GO

    -- This was good at scale

    SELECT claimNumber, maxSequence + x.x AS maxSequence

    INTO #tmp1

    FROM (

    SELECT

    claimNumber,

    MAX(maxSequence) maxSequence,

    ( ( MAX(maxSequence) / 20 ) + 1 ) * 20 [rollupTo]

    FROM #claims

    GROUP BY claimNumber

    ) c

    CROSS JOIN dbo.numbers x

    WHERE x.x <= [rollupTo] - maxSequence

    -- Solution 1 END

    ------------------------------------------------------------------------------------------------

    ------------------------------------------------------------------------------------------------

    -- Solution 2 START

    -- ChrisM@Work

    ------------------------------------------------------------------------------------------------

    DBCC DROPCLEANBUFFERS

    DBCC FREEPROCCACHE

    GO

    -- Demonstrate a solution using the sample data

    ;WITH

    e1(n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) dt (n)),

    e2(n) AS (SELECT 1 FROM e1 a CROSS JOIN e1 b),

    e4(n) AS (SELECT 1 FROM e2 a CROSS JOIN e2 b)

    SELECT

    d.claimNumber,

    maxSequence = d.LastSequenceNumber + x.n

    INTO #tmp2

    FROM (

    SELECT

    claimNumber,

    RowsToConstruct = 20-(MAX(maxSequence)%20),

    LastSequenceNumber = MAX(maxSequence)

    FROM #claims

    GROUP BY claimNumber

    ) d

    CROSS APPLY (

    SELECT TOP (RowsToConstruct)

    n = ROW_NUMBER() OVER (ORDER BY (SELECT NULL))

    FROM e4

    ) x

    GO

    -- Solution 2 END

    ------------------------------------------------------------------------------------------------

    See attachment for results. Call it a draw? : )

  • wBob (7/23/2014)


    I did trial that and honestly there is not a lot in it, with solution 1 (mine) slightly faster 5-10% on average at scale of 1 million. My test rig:

    ------------------------------------------------------------------------------------------------

    -- Setup START

    -- http://www.sqlservercentral.com/Forums/Topic1594823-2799-2.aspx?Update=1

    ------------------------------------------------------------------------------------------------

    USE tempdb

    GO

    IF OBJECT_ID('#claims') IS NOT NULL DROP TABLE #claims

    CREATE TABLE #claims

    (

    claimNumberINT,

    maxSequenceINT,

    PRIMARY KEY ( claimNumber, maxSequence )

    )

    GO

    ;WITH cte AS

    (

    SELECT TOP 1000000 ROW_NUMBER() OVER ( ORDER BY ( SELECT 1 ) ) rn

    FROM master.sys.columns c1

    CROSS JOIN master.sys.columns c2

    CROSS JOIN master.sys.columns c3

    )

    INSERT INTO #claims ( claimNumber, maxSequence )

    --VALUES ( 111, 17 ), ( 222, 38 ), ( 333, 20 )

    SELECT rn, rn % 33

    FROM cte

    GO

    IF OBJECT_ID('dbo.numbers') IS NULL

    BEGIN

    CREATE TABLE dbo.numbers ( x INT, CONSTRAINT PK_numbers PRIMARY KEY ( x ) )

    INSERT INTO dbo.numbers ( x )

    SELECT TOP 1000 ROW_NUMBER() OVER ( ORDER BY ( SELECT 1 ) ) x

    FROM master.sys.columns c1

    CROSS JOIN master.sys.columns c2

    CROSS JOIN master.sys.columns c3

    END

    GO

    ------------------------------------------------------------------------------------------------

    -- Solution 1 START

    ------------------------------------------------------------------------------------------------

    DBCC DROPCLEANBUFFERS

    DBCC FREEPROCCACHE

    GO

    -- This was good at scale

    SELECT claimNumber, maxSequence + x.x AS maxSequence

    INTO #tmp1

    FROM (

    SELECT

    claimNumber,

    MAX(maxSequence) maxSequence,

    ( ( MAX(maxSequence) / 20 ) + 1 ) * 20 [rollupTo]

    FROM #claims

    GROUP BY claimNumber

    ) c

    CROSS JOIN dbo.numbers x

    WHERE x.x <= [rollupTo] - maxSequence

    -- Solution 1 END

    ------------------------------------------------------------------------------------------------

    ------------------------------------------------------------------------------------------------

    -- Solution 2 START

    -- ChrisM@Work

    ------------------------------------------------------------------------------------------------

    DBCC DROPCLEANBUFFERS

    DBCC FREEPROCCACHE

    GO

    -- Demonstrate a solution using the sample data

    ;WITH

    e1(n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) dt (n)),

    e2(n) AS (SELECT 1 FROM e1 a CROSS JOIN e1 b),

    e4(n) AS (SELECT 1 FROM e2 a CROSS JOIN e2 b)

    SELECT

    d.claimNumber,

    maxSequence = d.LastSequenceNumber + x.n

    INTO #tmp2

    FROM (

    SELECT

    claimNumber,

    RowsToConstruct = 20-(MAX(maxSequence)%20),

    LastSequenceNumber = MAX(maxSequence)

    FROM #claims

    GROUP BY claimNumber

    ) d

    CROSS APPLY (

    SELECT TOP (RowsToConstruct)

    n = ROW_NUMBER() OVER (ORDER BY (SELECT NULL))

    FROM e4

    ) x

    GO

    -- Solution 2 END

    ------------------------------------------------------------------------------------------------

    See attachment for results. Call it a draw? : )

    Apart from the tally table being hard or inline, they're logically identical queries.

    “Write the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

Viewing 6 posts - 16 through 20 (of 20 total)

You must be logged in to reply to this topic. Login to reply