Поле обновления курсора SQL на основе предыдущего поля - PullRequest
1 голос
/ 24 июня 2019

Я использую 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

Расчет для 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 ]

4 голосов
/ 24 июня 2019

Нет необходимости в 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 означает строку до .

0 голосов
/ 24 июня 2019
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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...