UPDATE column with auto number depending on field value ?!

  • m.berggren (4/30/2009)


    Jeff:

    How does this so called "anchor" field works ?

    Here are a helpful link about statements in SQL Anywhere Studio 9.0.2

    http://www.ianywhere.com/developer/product_manuals/sqlanywhere/0902/en/html/index.html

    Regards

    Magnus

    Matt Miller did some testing and claimed that without it, SQL Server 2005 sometimes loses it's mind on the Quirky Update and that settles it down because it only has a single operand instead of two.

    I've not tested it myself... Matt is one of those folks I've tested with in the past and I pretty much take his word for it when he says he's ferreted something out. Probably not a good habit for me to get into, but I trust Matt, a lot.

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

  • john.arnott (4/30/2009)


    Well, I spent more time than I should have trying to get the cascaded value assignments (@counter = column = @counter + 1) to work inside a case statement. Finally the lightbulb went on and I split them out. Here's a solution that increments each of the separate range counters with its own case statement, then uses another case statement to choose which counter is appropriate.

    I hope this test data helps you (m.berrggren) towards an answer with your tables.

    Jeff,

    Is there a more efficient solution? I haven't tried it in SQL 2005, but figure a solution on that platform could be developed using row_number(). But this is SQL 2000.....

    drop Table #custTable

    create Table #custTable (number int, cat char(1) )

    insert #custTable values (0,'A')

    insert #custTable values (0,'A')

    insert #custTable values (0,'B')

    insert #custTable values (0,'B')

    insert #custTable values (0,'C')

    insert #custTable values (0,'C')

    insert #custTable values (0,'C')

    insert #custTable values (0,'A')

    insert #custTable values (0,'A')

    insert #custTable values (0,'B')

    insert #custTable values (0,'B')

    insert #custTable values (0,'C')

    insert #custTable values (0,'C')

    insert #custTable values (0,'C')

    DECLARE @counterA int

    select @counterA=30 -- starting value for this category

    DECLARE @counterB int

    select @counterB=90 -- starting value for this category

    UPDATE #custTable

    Set @counterA = case when cat = 'A' then @counterA + 1

    else @counterA

    end

    ,@counterB = case when cat = 'B' then @counterB + 1

    else @counterB

    end

    ,number = casewhen cat = 'A' then @counterA

    when cat = 'B' then @counterB

    else number

    end

    select * from #custTable

    The problem is, you haven't created the table correctly. In order for the quirky update to operate properly, the table absolutely MUST have a clustered index in the order that you want the update to be done. The problem with your data is, you have nothing to include in the clustered index that will maintain the proper order.

    Even with the code that you have in the quote above, there is no guarantee that it will work because you have nothing to guarantee the update order.

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

  • Jeff,

    Sorry for any confusion; I'm not the original poster. He posted in the SQL 2000 forum with just a snippet of code -- no table def's, nothing to go on. He may be doing his work on Sybase, but I took the forum as an indication of the feature set available -- I do not have Sybase.

    Since he hadn't provided one, I made up the sample table to at least try to point him in the right direction in terms of partitioning the data. I was aware that I wasn't specifying an order within the "cat" partition, figuring that since the OP hadn't specified one just yet, I'd let him at least figure out how to separate the different groups.

    I think from now on in this thread, I'll let the OP (m.berggren) provide the details of what his data really looks like and let us see what he's done with the information he's received so far.

  • Here is the code when i create the table. The fields are filled with values from a text file.

    Maybe there is something wrong when I create the table ?

    CREATE TABLE custom.citems (

    mi_seq INT PRIMARY KEY NOT NULL DEFAULT AUTOINCREMENT,

    number INT,

    cat CHAR (16),

    name CHAR (50)

    );

    INPUT INTO custom.citems FROM C:\items.txt format ASCII (number, cat, name);

    Regards

    Magnus

  • john.arnott (5/2/2009)


    Jeff,

    Sorry for any confusion; I'm not the original poster. He posted in the SQL 2000 forum with just a snippet of code -- no table def's, nothing to go on. He may be doing his work on Sybase, but I took the forum as an indication of the feature set available -- I do not have Sybase.

    Since he hadn't provided one, I made up the sample table to at least try to point him in the right direction in terms of partitioning the data. I was aware that I wasn't specifying an order within the "cat" partition, figuring that since the OP hadn't specified one just yet, I'd let him at least figure out how to separate the different groups.

    I think from now on in this thread, I'll let the OP (m.berggren) provide the details of what his data really looks like and let us see what he's done with the information he's received so far.

    That's what I get for posting without being under the influence of caffeine. I apologize for the mistaken identity, John. :blush:

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

  • m.berggren (5/2/2009)


    Here is the code when i create the table. The fields are filled with values from a text file.

    Maybe there is something wrong when I create the table ?

    CREATE TABLE custom.citems (

    mi_seq INT PRIMARY KEY NOT NULL DEFAULT AUTOINCREMENT,

    number INT,

    cat CHAR (16),

    name CHAR (50)

    );

    INPUT INTO custom.citems FROM C:\items.txt format ASCII (number, cat, name);

    Regards

    Magnus

    Again, this is Sybase, so I'm double checking because I just don't know for sure... does SyBase automatically make a clustered index as the default index for primary keys?

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

  • Jeff:

    I think youré right. I think it has something to with clustered index on the table.

    // Magnus

  • m.berggren (5/5/2009)


    Jeff:

    I think youré right. I think it has something to with clustered index on the table.

    // Magnus

    It absolutely does... UPDATE will update the data in the order of the clustered index. That's why they call it the "quirky update". Change your insert to include an ORDER BY for the correct order that the data should be processed in and I believe the PK on the autoincrement column will also be the default clustered index. Since that will be in the correct order (there is one exception which I don't believe applies here) because of the ORDER BY in the INSERT, you should be ok)

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

  • Finally i got i to work!

    Was searching the internet back and forward regarding this clustered index issue, found a lot of information and tried a lot without any luck.

    Then i changed the code you wrote Jeff and to the following. Little unsecure why it´s working now but is has something to do with changing from SET @counter = number = @counter+1 to set number=number+@counter, @counter=@counter+1;

    declare @counter int

    select @counter=0

    update custom.table1

    set number=number+@counter, @counter=@counter+1;

    // Magnus

  • I almost got this CASE update statement to work now for the catagory field. But the strange thing is that it´s only update´s cat "s1" like this

    cat "s1"

    10

    11

    12

    etc..

    cat "s2"

    40

    40

    40

    etc..

    If you remove the line WHERE t1.cat IN ('s1','s2') it doesn´t update at all.

    UPDATE custom.t1

    SET citems.number = '0'

    DECLARE @i1 int, @i2 int

    SELECT @i1=10, @i2=40

    UPDATE custom.t1

    SET number=

    CASE

    WHEN

    t1.cat='s1'

    THEN

    num+@i1

    WHEN

    t1.cat='s2'

    THEN

    num+@i2

    END

    ,@i1=

    CASE

    WHEN

    t1.cat='s1'

    THEN

    @i1+1

    END

    ,@i2=

    CASE

    WHEN

    t1.cat='s2'

    THEN

    @i2+1

    END

    WHERE t1.cat IN ('s1','s2')

    So, how come it´s only updating catagory "s1" ?

    Regards

    Magnus

  • Hi,

    The code below generates the following result.

    declare @i1 int

    declare @i2 int

    select @i1=10

    select @i2=40

    update custom.t1

    set num=

    case

    when

    t1.cat='s1'

    then

    number+@i1

    when

    t1.cat='s2'

    then

    nummber+@i2

    end

    Result:

    10

    10

    10

    40

    40

    40

    etc ..

    But if i change it to

    declare @i1 int

    declare @i2 int

    select @i1=10

    select @i2=40

    update custom.t1

    set num=

    case

    when

    t1.cat='s1'

    then

    number+@i1

    when

    t1.cat='s2'

    then

    nummber+@i2

    end,

    @i1=@i1+1,

    @i2=@i2+1

    Result:

    10

    11

    12

    61

    62

    63

    etc ..

    How come that the second CASE is starting at 60 when the variable is set to start at 40 ?

    Regards

    Magnus

  • The answer is in your "etc.". That is, you didn't show all the results, but I can see that regardless of whether you updated an s1 or s2 row, you've incremented both counters every time.

  • Old Hand:

    Well, "etc" isn´t a part of the result actually. I just wrote it to mark a stop in the result of the query. So don´t mind about the "etc" .. 🙂 .. just to demostrate the output.

  • Grasshopper,

    Sorry to confuse you. By saying the answer is in the "etc.", I was trying to get you to look at the overall process. Your actual results would have shown about 20 results in the 10 range (10, 11, 12...).

    The second half of my response points out the reason the S2 rows start at 61: " regardless of whether you updated an s1 or s2 row, you've incremented both counters every time. "[/size]

    You may want to take another look at the code I posted for you Posted 4/30/2009 7:34:23 PM:

    drop Table #custTable

    create Table #custTable (number int, cat char(1) )

    insert #custTable values (0,'A')

    insert #custTable values (0,'A')

    insert #custTable values (0,'B')

    insert #custTable values (0,'B')

    insert #custTable values (0,'C')

    insert #custTable values (0,'C')

    insert #custTable values (0,'C')

    insert #custTable values (0,'A')

    insert #custTable values (0,'A')

    insert #custTable values (0,'B')

    insert #custTable values (0,'B')

    insert #custTable values (0,'C')

    insert #custTable values (0,'C')

    insert #custTable values (0,'C')

    DECLARE @counterA int

    select @counterA=30 -- starting value for this category

    DECLARE @counterB int

    select @counterB=90 -- starting value for this category

    UPDATE #custTable

    Set @counterA = case when cat = 'A' then @counterA + 1

    else @counterA

    end

    ,@counterB = case when cat = 'B' then @counterB + 1

    else @counterB

    end

    ,number = casewhen cat = 'A' then @counterA

    when cat = 'B' then @counterB

    else number

    end

    select * from #custTable

  • Old Hand:

    Thx, i just tried youré code snippet and it don´t work. Well, it works but it doesn´t give right the output. The result is:

    number, cat

    31, A

    31, A

    91, B

    91, B

    0, C

    0, C

    0, C

    31, A

    31, A

    91, B

    91, B

    0, C

    0, C

    0, C

    I think i has something to do how the syntax is written. Beacuse if i change it to the code below it work´s fine. So there has to something wrong whitin the case statement. If i cut out the CASE statement and instead write:

    UPDATE custom.custTable

    set number=number+@counterA, @counterA=@counterA+1

    where custTable.cat = 'A'

    UPDATE custom.custTable

    set number=number+@counterB, @counterB=@counterB+1

    where custTable.cat = 'B'

    /Magnus

Viewing 15 posts - 16 through 30 (of 39 total)

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