Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cursor to update a row with values from the previous and current rows

Fellow Query Writers,

I have a table as follows:

myTable t1
col2 col3
 2    1
 3    0
 4    0
 5    0
 6    0

and I want to update each zero on col3 with the value of col3 in the previous row plus the value of col2 in the current row. So my table would de like the following:

myTable t1
col2 col3
 2    1 
 3    4  (1+3)
 4    8  (4+4)
 5    13 (5+8) 
 6    19 (6+13)

I'm missing the logic here, short-sightedness perhaps. I was trying it with a cursor as follows:

DECLARE @var3 FLOAT

DECLARE cursor3 CURSOR FOR
SELECT col2, col3 FROM table1
FOR UPDATE OF col3
OPEN cursor3


FETCH FIRST FROM cursor3
WHILE (@@FETCH_STATUS > -1)
BEGIN
 UPDATE @table1
 SET col3 = isnull(@var3, 0) + isnull(col2, 0)
 WHERE CURRENT OF cursor3
 FETCH NEXT FROM cursor3 INTO @var3
END

but it's wrong. Any ideas?

Thanks in advance.

like image 363
Lynx Kepler Avatar asked Nov 03 '10 17:11

Lynx Kepler


People also ask

Can we use cursor for update in SQL?

You can update rows of data as you retrieve them by using a cursor. On the select-statement, use FOR UPDATE OF followed by a list of columns that may be updated. Then use the cursor-controlled UPDATE statement. The WHERE CURRENT OF clause names the cursor that points to the row you want to update.

Can cursors operate on multiple rows?

The multiple-row FETCH statement can be used with both serial and scrollable cursors. The operations used to define, open, and close a cursor for a multiple-row FETCH remain the same. Only the FETCH statement changes to specify the number of rows to retrieve and the storage where the rows are placed.

Which command is used to change the value of certain rows?

The SQL UPDATE query is used to modify the existing records in a table. We can use the WHERE clause with the UPDATE query to update the selected rows, otherwise all the rows would be affected.


2 Answers

OK, Try this.

CREATE TABLE MyTable (Id INT Identity, Col2 int, Col3 int)

INSERT INTO MyTable (Col2, Col3)
VALUES (2,1), (3,0), (4,0),(5,0),(6,0)

SELECT * from MyTable

WHILE (SELECT COUNT(*) FROM MyTable WHERE Col3=0) > 0
BEGIN
    UPDATE TOP (1) MyTable
    SET CoL3 = (Mytable.col2 + (select col3 from mytable t2 where (t2.id = mytable.id-1)))
    WHERE Col3 = 0
END

SELECT * from MyTable

Uses a WHILE loop which should be faster than a cursor under most circumstances.

like image 144
JNK Avatar answered Oct 18 '22 05:10

JNK


I added an identity column to my table and ended up using a code like this:

DECLARE @saldo_Q_previous FLOAT
DECLARE @ID INTEGER

DECLARE cursor3 CURSOR FOR
SELECT ID FROM @myTable
FOR UPDATE OF col2
OPEN cursor3

FETCH NEXT FROM cursor3 INTO @ID
FETCH NEXT FROM cursor3 INTO @ID

WHILE (@@FETCH_STATUS > -1)
BEGIN

    SET @col2_previous = ISNULL((SELECT TOP 1 col2 FROM @myTable WHERE ID < @ID ORDER BY ID DESC), 0)
    SET @vrQ = ISNULL((SELECT TOP 1 vr_Q FROM @myTable WHERE ID < @ID ORDER BY ID DESC), 0)

    UPDATE @myTable
    SET col2 = isnull(@col2_previous, 0) + isnull(vrMov_Q, 0)
    WHERE CURRENT OF cursor3

    FETCH NEXT FROM cursor3 INTO @ID
END

CLOSE cursor3
DEALLOCATE cursor3

It solved my problem. Thank you all.

like image 30
Lynx Kepler Avatar answered Oct 18 '22 06:10

Lynx Kepler