SQL Server: цикл по одной таблице, получение суммы до достижения порогового значения и обновление значения суммы в другой таблице. - PullRequest
0 голосов
/ 08 июня 2019

У меня есть две таблицы:

Sales таблица:

enter image description here

Returns таблица:

enter image description here

Я должен пройтись по таблице Sales и получить сумму всех Qty на основе комбинации Material+Batch+customer, пока она не превысит значение Return_qtyи обновите значение Summed в таблице Returns.

Это желаемый результат:

enter image description here

Как видно из таблицы Sales до Sales_Invoice 4 толькосчитается, что оно превысило значение return_Qty.

Что я пробовал до сих пор?

Я пытался использовать цикл while для циклического прохождения и вычисления промежуточного итога.Но это не работает.Возможно, это неправильный подход.

Любые входные данные будут высоко оценены.

Ответы [ 2 ]

1 голос
/ 08 июня 2019

Попробуйте это:

DECLARE @Sales TABLE
(
    [Sales_Invoice] SMALLINT
   ,[Invoice_Date] DATE
   ,[Material] VARCHAR(3)
   ,[Batch] VARCHAR(2)
   ,[Customer] VARCHAR(4)
   ,[Qty] SMALLINT
);

DECLARE @Returns TABLE
(
    [Return_Invoice] SMALLINT
   ,[Invoice_Date] DATE
   ,[Material] VARCHAR(3)
   ,[Batch] VARCHAR(2)
   ,[Customer] VARCHAR(4)
   ,[Return_Qty] SMALLINT
   ,[Sales_Qty] SMALLINT
);

INSERT INTO @Sales ([Sales_Invoice], [Invoice_Date], [Material], [Batch], [Customer], [Qty])
VALUES (1, '2019-06-07', 'AB1', 'B1', 'B001', 50)
      ,(2, '2019-06-07', 'AB1', 'B1', 'B001', 20)
      ,(3, '2019-06-06', 'AB1', 'B1', 'B001', 25)
      ,(4, '2019-06-06', 'AB1', 'B1', 'B001', 11)
      ,(5, '2019-06-06', 'AB1', 'B1', 'B001', 20)
      ,(6, '2019-06-01', 'BA2', 'C1', 'Y001', 100);

INSERT INTO @Returns ([Return_Invoice], [Invoice_Date], [Material], [Batch], [Customer], [Return_Qty])
VALUES (212, '2019-06-08', 'AB1', 'B1', 'B001', 100);

WITH DataSource AS
(
    SELECT [Material], [Batch], [Customer]
          ,SUM([Qty]) OVER (PARTITION BY [Material], [Batch], [Customer] ORDER BY [Sales_Invoice] ASC) AS [Return_Qty]
    FROM @Sales
)
UPDATE @Returns
SET [Sales_Qty] = DS.[Return_Qty]
FROM @Returns R
INNER JOIN 
(
    SELECT [Material], [Batch], [Customer]
           ,MIN([Return_Qty]) AS [Return_Qty]
    FROM DataSource
    WHERE [Return_Qty] >= 100
    GROUP BY [Material], [Batch], [Customer]
) DS
    ON R.[Material] = DS.[Material]
    AND R.[Batch] = DS.[Batch]
    AND R.[Customer] = DS.[Customer];

SELECT *
FROM @Returns;

enter image description here

Если вы хотите быть более динамичным, вы можете использовать следующее:

WITH DataSource AS
(
    SELECT [Material], [Batch], [Customer]
          ,SUM([Qty]) OVER (PARTITION BY [Material], [Batch], [Customer] ORDER BY [Sales_Invoice] ASC) AS [Return_Qty]
    FROM @Sales
)
UPDATE @Returns
SET [Sales_Qty] = DataSource.[Return_Qty]
FROM @Returns R
CROSS APPLY 
(
    SELECT  DS.[Material],  DS.[Batch],  DS.[Customer]
           ,MIN(DS.[Return_Qty]) AS [Return_Qty]
    FROM DataSource DS
    WHERE  DS.[Return_Qty] >= R.[Return_Qty]
        AND R.[Material] = DS.[Material]
        AND R.[Batch] = DS.[Batch]
        AND R.[Customer] = DS.[Customer]
    GROUP BY [Material], [Batch], [Customer]
) DataSource;
0 голосов
/ 08 июня 2019

Вы действительно должны показать свое заявление while в своем посте - не могли бы вы сделать это, пожалуйста?

Я думаю, что обычное табличное выражение, использующее рекурсию, является хорошим решением для вас. что-то вроде ...

;
WITH
cte1 AS
( 
SELECT
RANK() OVER
    (ORDER BY S.Material, S.Batch, S.Customer) GroupId,
RANK() OVER
    (
    PARTITION BY S.Material, S.Batch, S.Customer,
    ORDER BY S.INVOICE_Date) Seqn,
S.Material, S.Batch, S.Customer, S.qty, R.Return_qty
FROM
    Sales S
JOIN
    Returns R
    ON S.Material = R.Material AND S.Batch = R.Batch AND S.Customer = R.Customer
),
cte2 AS
( 
SELECT
GroupId, Seqn,Material, Batch, Customer, qty AS TriggeringQty, Return_qty
FROM cte1 
WHERE seqn  =1
UNION ALL
SELECT
cte1.GroupId, cte1.Seqn, cte1.Material, cte1.Batch, cte1.Customer,
    cte1.qty + cte2.qty, cte1.Return_qty
FROM cte2
    JOIN cte1
    ON cte1.GroupId = cte2.GroupID AND cte1.seqn = cte2.seqn+1
WHERE 
cte2.qty < 100 AND cte1.seqn + cte2.seqn+1 >= Return_qty )

UPDATE R
SET R.Sales_qty = cte2.triggeringqty
FROM Returns R
JOIN cte2 S ON
S.Material = R.Material AND S.Batch = R.Batch AND S.Customer = R.Customer
WHERE cte2.triggeringqty >= 100;

Извините, я не пробовал вышеизложенное, поэтому, вероятно, не запустится, но, надеюсь, вы увидите, что происходит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...