游标用前一行和当前行的值更新行

发布于 2024-09-30 15:22:06 字数 704 浏览 1 评论 0原文

各位查询编写者,

我有一个如下表:

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

我想用前一行中 col3 的值加上当前行中 col2 的值来更新 col3 上的每个零。所以我的桌子会像下面这样:

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

但这是错误的。 有什么想法吗?

提前致谢。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

拥抱我好吗 2024-10-07 15:22:06

好的,试试这个。

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 循环,在大多数情况下它应该比光标更快。

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.

寻找我们的幸福 2024-10-07 15:22:06

我在表中添加了一个标识列,最终使用了这样的代码:

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

它解决了我的问题。谢谢大家。

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.

-残月青衣踏尘吟 2024-10-07 15:22:06

下面是一个使用公用表表达式 (CTE) 更新数据的 UPDATE 语句。

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
;

Here is a single UPDATE statement that uses common table expressions (CTE) to update the data.

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
;
哆啦不做梦 2024-10-07 15:22:06

FWIW 使用 CURSOR 的主要且令人信服的原因是,如果不这样做,会对您的 RDBMS 造成太大的影响。您几乎总是可以使用 WHILE 循环来代替 CURSOR;一次处理一条记录;当您出于某种原因可能需要迭代大量记录时,它会非常有用... CURSOR 操作比等效的 SET 操作的效率呈指数级提高。

所以总的来说,这取决于速度和速度。开销与效率...

游标几乎是最慢的方式,但开销最小,即使在 MSSQL 2012 中仍然有用...

FWIW The major, compelling reason to use a CURSOR is when not doing so, will put too much of a hit on your rdbms. You can almost always use a WHILE loop instead of a CURSOR; processing ONE record at a time; can be quite useful when for whatever reason you may need to iterate a large number of records... CURSOR operations are exponentially more efficient than the equivalent SET operation.

So in general it comes down to speed & overhead vs. efficiency...

CURSORS are pretty much the slowest way to go, but have the least amount of overhead and are still useful even in MSSQL 2012 ...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文