Sql server 基于上一个字段的SQL游标更新字段

Sql server 基于上一个字段的SQL游标更新字段,sql-server,tsql,database-cursor,Sql Server,Tsql,Database Cursor,我正在使用SQL Server 2016 我有这张桌子: RowID SKU Shop Week Prioirty Replen Open_Stk --------------------------------------------------------------- 1 111 100 1 1 400 5000 2 111 20

我正在使用SQL Server 2016

我有这张桌子:

RowID     SKU     Shop    Week   Prioirty   Replen    Open_Stk 
---------------------------------------------------------------
 1        111     100      1        1        400         5000           
 2        111     200      1        2        400         NULL
 3        111     300      1        3        400         NULL
 4        111     400      1        4        400         NULL
这是期望的结果:

RowID     SKU     Shop    Week   Prioirty   Replen    Open_Stk 
---------------------------------------------------------------
 1        111     100      1        1        400         5000           
 2        111     200      1        2        400         4600
 3        111     300      1        3        400         4200
 4        111     400      1        4        400         3800
开放式Stk的计算基于上一行:

[Open_Stk] = [Open_Stk]-IIF([Replen]<=IIF([Open_Stk]>=0,[Open_Stk],0),[Replen],0)
我正在使用下面的光标更新Open_Stk,但什么也没有发生-我缺少什么:

DECLARE @CurrentRow INT;
DECLARE @PreviousRow INT

DECLARE ShopRank CURSOR FOR
    SELECT RowID
    FROM [tmp_tblTEST]
    ORDER BY [SKU], [Week],Priority

OPEN ShopRank
FETCH NEXT FROM ShopRank INTO @CurrentRow

WHILE @@FETCH_STATUS = 0
BEGIN 
    IF ((SELECT [Open_Stk] FROM [tmp_tblTEST] WHERE RowID = @CurrentRow) IS NULL)
    BEGIN
        UPDATE [tmp_tblTEST]
        SET [Open_Stk] = [Open_Stk] - IIF([Replen] <= IIF([Open_Stk] >= 0, [Open_Stk], 0), [Replen], 0) 
        WHERE RowID = @PreviousRow
    END

    SET @PreviousRow = @CurrentRow

    FETCH NEXT FROM ShopRank INTO @CurrentRow
END

CLOSE ShopRank
DEALLOCATE ShopRank
这里根本不需要光标。这是一个小小的猜测,但我怀疑你真正想要的是这样的:

SELECT V.RowID,
       V.SKU,
       V.Shop,
       V.[Week],
       V.Priority,
       V.Replen,
       FIRST_VALUE(V.Open_Stk) OVER (PARTITION BY V.SKU ORDER BY V.[Week], V.Priority
                                     ROWS UNBOUNDED PRECEDING) -
       ISNULL(SUM(V.Replen) OVER (PARTITION BY V.SKU ORDER BY V.[Week], V.Priority
                                  ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING),0) AS OpenStk
FROM (VALUES (1,111,100,1,1,400,5000),           
             (2,111,200,1,2,400,NULL),
             (3,111,300,1,3,400,NULL),
             (4,111,400,1,4,400,NULL))V(RowID,SKU,Shop,[Week],Priority,Replen,Open_Stk)
ORDER BY V.Sku,
         V.[Week],
         V.Priority;
使用原液

第一个值按照tin上的说明执行。该总和从第一行的Open_Stk值中减去前一行的值;制作最终结果集。由于rows-BETWEEN子句,它只引用前面的行。ROWS UNBOUNDED表示从分区范围的开始处开始,1 previous表示前面的行。

这里根本不需要光标。这是一个小小的猜测,但我怀疑你真正想要的是这样的:

SELECT V.RowID,
       V.SKU,
       V.Shop,
       V.[Week],
       V.Priority,
       V.Replen,
       FIRST_VALUE(V.Open_Stk) OVER (PARTITION BY V.SKU ORDER BY V.[Week], V.Priority
                                     ROWS UNBOUNDED PRECEDING) -
       ISNULL(SUM(V.Replen) OVER (PARTITION BY V.SKU ORDER BY V.[Week], V.Priority
                                  ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING),0) AS OpenStk
FROM (VALUES (1,111,100,1,1,400,5000),           
             (2,111,200,1,2,400,NULL),
             (3,111,300,1,3,400,NULL),
             (4,111,400,1,4,400,NULL))V(RowID,SKU,Shop,[Week],Priority,Replen,Open_Stk)
ORDER BY V.Sku,
         V.[Week],
         V.Priority;
使用原液


第一个值按照tin上的说明执行。该总和从第一行的Open_Stk值中减去前一行的值;制作最终结果集。由于rows-BETWEEN子句,它只引用前面的行。“行无边界”表示从分区范围的开始处开始,前面的1表示前面的行。

为什么在这里使用光标?如果您需要引用前一行,为什么不使用超前/滞后函数呢?事实上,这看起来像是一个前导行无限的求和的候选者。为什么在这里使用光标呢?如果您需要引用前一行,为什么不使用超前/滞后函数呢?事实上,这看起来像是一个具有无边界行的和的候选者是-这就是我所需要的。但是,RowID可能不会简单地遵循数字顺序-因此它需要先按[SKU]、[Week]、优先级排序,然后根据@Michael子句更改顺序以反映您的需要。我只是假设RowID是正确的选择;“因为它在这里产生了正确的结果。我已经更新了答案,以反映您所需的顺序,@Michael,但希望您自己也能解决这个问题。”是的,这就是我需要的。但是,RowID可能不会简单地遵循数字顺序-因此它需要先按[SKU]、[Week]、优先级排序,然后根据@Michael子句更改顺序以反映您的需要。我只是假设RowID是正确的选择;“因为它在这里产生了正确的结果。我已经更新了答案,以反映您所需的顺序,@Michael,但希望您自己也能解决这个问题。”