基于前几行的T SQL游标计算

时间:2019-06-28 10:35:10

标签: sql-server tsql database-cursor

我正在使用SQL Server 2016。

我有这张桌子:

CREATE TABLE [tblTEST] 
(
    RowID INT,
    SKU INT,
    Shop INT,
    Week INT,
    ShopPriority INT,    
    ShopStock INT,       
    Target_Stock INT,    
    Outbound INT,        
    Ration_Replen INT,   
    Open_Stk INT,        
    Closing_Stk INT,     
    Real_Open INT,       
    Unconst_Replen INT,     
    Rounded_Replen INT   
);

并填充值:

INSERT INTO dbo.tblTEST
VALUES (1, 111, 100, 1, 1, 50, 50, 50, 0, 5, 5, 5, 0, 0),
       (2, 111, 100, 1, 2, 50, 50, 50, 0, 0, 0, 0, 0, 0),
       (3, 111, 100, 1, 3, 50, 50, 50, 0, 0, 0, 0, 0, 0),
       (4, 111, 100, 1, 4, 50, 50, 50, 0, 0, 0, 0, 0, 0);

这将创建以下内容(由于此页面上的格式问题,我无法获得所有的零:

RowID     SKU     Shop    Week   Prioirty   ShopStock    Target_Stock   Outbound     Ration_Replen    Open_Stk    Closing_Stk    Real_Open    Unconst_Replen   Rounded_Replen
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1        111     100      1        1          50           50            50              0               5            5           5                               
  2        111     200      1        2          50           50            50              0                                                          
  3        111     300      1        3          50           50            50              0
  4        111     400      1        4          50           50            50      

但是,我需要进行计算以创建以下内容:

    RowID     SKU     Shop    Week   Prioirty   ShopStock    Target_Stock   Outbound     Ration_Replen    Open_Stk    Closing_Stk    Real_Open    Unconst_Replen   Rounded_Replen
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      1        111     100      1        1          50           50            50              0               5            5           5                               
      2        111     200      1        2          50           50            50              0               5            5           5                    
      3        111     300      1        3          50           50            50              0               5            5           5
      4        111     400      1        4          50           50            50              0               5            5           5   

我正在使用下面的光标尝试实现这一目标:

DECLARE @CurrentRow INT;
DECLARE @PreviousRow INT

DECLARE MinQty CURSOR FOR
    SELECT RowID
    FROM [tblTEST]
    WHERE [Week] IS NOT NULL
    ORDER BY [SKU], [Week], ShopPriority

OPEN MinQty

FETCH NEXT FROM MinQty INTO @CurrentRow

WHILE @@FETCH_STATUS = 0
BEGIN
    IF ((SELECT [Open_Stk]
         FROM [tblTEST]
         WHERE RowID = @CurrentRow) IS NULL)
    BEGIN
        UPDATE [tblTEST]
        SET [Open_Stk] = (SELECT [Closing_Stk]
                          FROM [tblTEST]
                          WHERE RowID = @PreviousRow)
        WHERE RowID = @CurrentRow

        UPDATE [tblTEST]
        SET [Real_Open] = (SELECT IIF([Open_Stk] >= 0, [Open_Stk], 0)
                           FROM [tblTEST]
                           WHERE RowID = @CurrentRow),          
            [Unconst_Replen] = (SELECT IIF(ShopStock + [Ration_Replen] < Target_Stock, IIF(Target_Stock - (ShopStock + [Ration_Replen]) < [Real_Open], Target_Stock - (ShopStock + [Ration_Replen]), [Real_Open]), 0)
                                FROM [tblTEST]
                                WHERE RowID = @CurrentRow),                 
            Rounded_Replen = (SELECT IIF(Unconst_Replen = 0, 0, IIF(Unconst_Replen < Outbound, Outbound, Unconst_Replen))
                              FROM [tblTEST]
                              WHERE RowID = @CurrentRow),
            Closing_Stk = (SELECT Open_Stk - IIF(Rounded_Replen > IIF(Open_Stk >= 0, Open_Stk, 0), 0, Rounded_Replen)
                           FROM [tblTEST]
                           WHERE RowID = @CurrentRow)
        WHERE RowID = @CurrentRow
    END

    SET @PreviousRow = @CurrentRow

    FETCH NEXT FROM MinQty INTO @CurrentRow
END

CLOSE MinQty
DEALLOCATE MinQty

但是,光标不执行任何操作-值保持不变,并且未计算Open_Stk \ Closing_Stk和Real_Open-我缺少什么?

2 个答案:

答案 0 :(得分:1)

在这种情况下无需使用游标,如果您需要根据上一行进行计算,则可以使用SQL Server的内置函数-请参阅以下示例作为参考,并且可以根据需要进行更改您的要求。

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

答案 1 :(得分:0)

如果有人感兴趣,我可以解决。真的很傻-

我刚刚更改了以下代码段:

BEGIN
    IF ((SELECT [Open_Stk]
         FROM [tblTEST]
         WHERE RowID = @CurrentRow) IS NULL)

BEGIN
    IF (
            (
                SELECT [Open_Stk]
                FROM [tblTEST]
                WHERE RowID = @CurrentRow
                ) = 0

默认值为0,而不是NULL。哦,谢谢所有对此发表评论的人。