T SQL游标更新字段基于上一个字段

时间:2019-06-24 11:13:15

标签: sql-server tsql database-cursor

我正在使用SQL Server2016。

我有这张桌子:

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

Open_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

2 个答案:

答案 0 :(得分:4)

这里完全不需要CURSOR。这是一些猜测工作,但我怀疑,您在这里实际遇到的事情是这样的:

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;

DB<>Fiddle (使用原始解决方案)

FIRST_VALUE完成了锡上的操作。 SUM从第一行的Open_Stk的值中减去每个先前行的值;制作最终结果集。由于ROWS BETWEEN子句,它仅引用先前的行。 ROWS UNBOUNDED表示从分区范围的开始,1 PRECEDING表示行在先

答案 1 :(得分:0)

WITH result AS 
( 
    SELECT
        a.*, ISNULL(NULLIF(a.Open_Stk, 0), 0) AS Output 
    FROM
        table1 a
    JOIN
        table1 b ON a.Prioirty = b.Prioirty - 1

    UNION ALL 

    SELECT 
        a.*, output - a.Replen
    FROM
        table1 a
    JOIN
        result b ON a.Prioirty = b.Prioirty+1 
) 
SELECT * 
FROM result
WHERE output > 0