курсор для обновления строки значениями из предыдущей и текущей строк - PullRequest
6 голосов
/ 03 ноября 2010

Fellow Query Writers,

У меня есть следующая таблица:

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

, и я хочу обновить каждый ноль на col3 значением col3 в предыдущей строке плюс значениеиз col2 в текущей строке.Таким образом, мой стол будет выглядеть следующим образом:

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

Мне не хватает логики здесь, возможно, близорукости.Я пытался сделать это с помощью курсора следующим образом:

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

но это неправильно.Есть идеи?

Заранее спасибо.

Ответы [ 4 ]

9 голосов
/ 03 ноября 2010

ОК, попробуйте это.

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

Использует цикл WHILE, который в большинстве случаев должен быть быстрее курсора.

2 голосов
/ 17 ноября 2010

Я добавил в таблицу столбец идентификаторов и в итоге использовал такой код:

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

Это решило мою проблему.Спасибо всем.

0 голосов
/ 17 сентября 2013

FWIW Основная, непреодолимая причина использовать CURSOR в том случае, если вы этого не сделаете, слишком сильно ударит по вашим rdbms.Вы почти всегда можете использовать цикл WHILE вместо CURSOR;обработка ОДНОЙ записи за раз;может быть весьма полезным, когда по какой-либо причине вам может понадобиться выполнить итерацию большого количества записей ... Операции CURSOR экспоненциально более эффективны, чем эквивалентные операции SET.

Таким образом, в общем, все сводится к скорости и накладным расходам в сравнении с эффективностью ...

КУРСОРЫ - это, пожалуй, самый медленный путь, но он имеет наименьшее количество накладных расходов и все еще полезен дажев MSSQL 2012 ...

0 голосов
/ 03 ноября 2010

Вот один оператор UPDATE, который использует общие табличные выражения (CTE) для обновления данных.

WITH myTable2 AS
    (
    SELECT col2, col3, ROW_NUMBER() OVER (ORDER BY col2) AS sequence
    FROM myTable
    ),
  newTable AS
    (
    SELECT t1.col2, SUM(t2.col2) - SUM(t2.col3) AS col3
    FROM myTable2 t1
    LEFT OUTER JOIN myTable2 t2 ON t1.sequence >= t2.sequence
    GROUP BY t1.col2
    )

UPDATE myTable
SET col3 = newTable.col3
FROM myTable
JOIN newTable on myTable.col2 = newTable.col2
;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...