going crazy with update statement! Plz help

  • hi everybody,

    I have a big problem with update statement, let me mention the situation by exact script and results!

    first create trans table=>

    create table trans(

    id bigint identity(1,1) not null,

    price decimal(18,0) null,

    relatedid bigint null)

    Then fill it by this script

    Insert into trans (price,relatedid)values(100,NULL)

    Insert into trans (price,relatedid)values(100,NULL)

    Insert into trans (price,relatedid)values(500,NULL)

    Insert into trans (price,relatedid)values(1,NULL)

    Insert into trans (price,relatedid)values(1,3)

    Now run this query!

    Update trans

    set price=(case when relatedid is null then (select avg(price) from trans where id<=t.id)

    else (select top(1) price from trans where id=t.relatedid) end)

    from trans t

    After execution of query I expect this result:

    id-----price-----relatedid

    1 100 NULL

    2 300 NULL

    3 200 NULL

    4 200 3 <======== realy expected!!!!

    But this is the result!!!

    id-----price-----relatedid

    1 100 NULL

    2 300 NULL

    3 200 NULL <======= #3 row

    4 1 3 <===== wrong value, i mean this is the value before update

    row with id 3 has been updated before but update doesnt know this!!!!!

    WHAT I NEED i need to get expected result from this execution!!!! plzzzzzzzzzzz

  • Please will you post your actual update statement, since the one you posted has two syntax errors in it.

    Thanks

    John

  • I tried to execute your update statement in SQL 2005 and '=<' is not working on that hence I modified to '<=' as follows.

    Update TempTrans

    set price=(case when relatedid is null then (select avg(price) from TempTrans where id<=t.id)

    else (select top(1) price from TempTrans where id=t.relatedid) end)

    from TempTrans t

    and the following is the output after executing update statement.

    idpricerelatedid

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

    1100NULL

    2100NULL

    3233NULL

    4175NULL

    55003

    - Manish

  • Manish_ (4/13/2011)


    I tried to execute your update statement in SQL 2005 and '=<' is not working on that hence I modified to '<=' as follows.

    Update TempTrans

    set price=(case when relatedid is null then (select avg(price) from TempTrans where id<=t.id)

    else (select top(1) price from TempTrans where id=t.relatedid) end)

    from TempTrans t

    and the following is the output after executing update statement.

    idpricerelatedid

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

    1100NULL

    2100NULL

    3233NULL

    4175NULL

    55003

    after update value of row #3 is 233 ... look at the result row #5 has updated to 500 which it's before update value of row #3 , this is my exact problem! row #5 must be updated to 233

  • John Mitchell-245523 (4/13/2011)


    Please will you post your actual update statement, since the one you posted has two syntax errors in it.

    Thanks

    John

    Thank u John... I just edited it a couple ago... plz take look at it

  • It looks like you will need to perform 2 updates, one for the average and a second for the related price update.

    UPDATE trans

    SET price = (select avg(price) from trans where id<=t.id)

    from trans t

    WHERE relatedid IS NULL

    UPDATE trans

    SET price = (select top(1) price from trans where id=t.relatedid)

    From trans t

    WHERE relatedid > 0

  • You need to do your update in two passes:

    ;WITH t1 AS (SELECT id,price,relatedid FROM trans)

    UPDATE trans

    SET price=(

    SELECT AVG(price)

    FROM t1

    WHERE t1.id<=trans.id

    )

    WHERE relatedid IS NULL

    ;WITH t1 AS (SELECT id,price,relatedid FROM trans)

    UPDATE trans

    SET price=(

    SELECT TOP(1) price

    FROM t1

    WHERE t1.id=trans.relatedid

    )

    WHERE relatedid IS NOT NULL

    John

  • Another way with just one update.

    UPDATE trans

    SET price = CASEWHEN relatedID IS NOT NULL

    THEN

    (select avg(price) from trans where id<=t.relatedid)

    ELSE

    (select avg(price) from trans where id<=t.id)

    END

    FROM trans t

  • John Mitchell-245523 (4/13/2011)


    You need to do your update in two passes:

    ;WITH t1 AS (SELECT id,price,relatedid FROM trans)

    UPDATE trans

    SET price=(

    SELECT AVG(price)

    FROM t1

    WHERE t1.id<=trans.id

    )

    WHERE relatedid IS NULL

    ;WITH t1 AS (SELECT id,price,relatedid FROM trans)

    UPDATE trans

    SET price=(

    SELECT TOP(1) price

    FROM t1

    WHERE t1.id=trans.relatedid

    )

    WHERE relatedid IS NOT NULL

    John

    In two step update method the result goes wrong! because the value of not null relatedid rows are clearly involves in avg operation! I mean when row #3 has wrong value in step one avg of next row is wrong also, so this operation must executed in one step!

  • DB Dan (4/13/2011)


    Another way with just one update.

    UPDATE trans

    SET price = CASEWHEN relatedID IS NOT NULL

    THEN

    (select avg(price) from trans where id<=t.relatedid)

    ELSE

    (select avg(price) from trans where id<=t.id)

    END

    FROM trans t

    Thank you DB Dan! I LOVE THIS I must implement this in real project! I'll be right back

  • DB Dan (4/13/2011)


    Another way with just one update.

    UPDATE trans

    SET price = CASEWHEN relatedID IS NOT NULL

    THEN

    (select avg(price) from trans where id<=t.relatedid)

    ELSE

    (select avg(price) from trans where id<=t.id)

    END

    FROM trans t

    result goes wrong again! the problem is here... next avg row needs before updated row value! the problem in before related row has been solved but for next avg rows problem still exists! PLZZZ help :crying:

  • simorgh,

    A set based update works on the SELECT statement, which is processed and returns a record set before any updates are actually done. If you expect a cumulative sequential update on a column that is has the update information from a column that is earlier in the sort order you can't do it in a single update statement. There are 2 options for this.

    A cursor that updates single rows in sequence or build a temp table with the expected accumulated results (see Jeff Moden's article on the quirky update method for running totals) and use that to join to your table and do the update.

    Todd Fifield

Viewing 12 posts - 1 through 11 (of 11 total)

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