Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

CTE - aggiorna in modo ricorsivo la quantità fino al totale consumato

[email protected] table mimics inserted virtual table from AFTER INSERT triggers on [dbo].[myOrder] table
DECLARE @inserted TABLE 
(
  [Account] [float] NOT NULL,
  [Item] [float] NOT NULL,
  [Quantity] [float] NOT NULL
);

INSERT  @inserted 
VALUES  (12345, 1, 50);

WITH CteRowNumber
AS
(
    SELECT   inv.ID
            ,inv.Account
            ,inv.Item
            ,inv.Quantity
            ,inv.QuantitySold
            ,i.Quantity QuantityOrdered
            ,ROW_NUMBER() OVER(PARTITION BY inv.Account,inv.Item ORDER BY inv.ID ASC) RowNumber
    FROM    myInventory inv
    INNER JOIN @inserted i ON inv.Account = i.Account 
    AND     inv.Item = i.Item 
    WHERE   inv.Quantity > inv.QuantitySold
),  CteRecursive
AS
(
    SELECT   a.ID
            ,a.Account
            ,a.Item
            ,a.RowNumber 
            ,CASE 
                WHEN a.Quantity - a.QuantitySold < a.QuantityOrdered THEN a.Quantity - a.QuantitySold 
                ELSE a.QuantityOrdered
            END QuantitySoldNew
            ,CASE 
                WHEN a.Quantity - a.QuantitySold < a.QuantityOrdered THEN a.Quantity - a.QuantitySold 
                ELSE a.QuantityOrdered
            END RunningTotal
    FROM    CteRowNumber a
    WHERE   a.RowNumber = 1
    UNION ALL
    SELECT   crt.ID
            ,crt.Account
            ,crt.Item
            ,crt.RowNumber
            ,CASE 
                WHEN prev.RunningTotal + (crt.Quantity - crt.QuantitySold) < crt.QuantityOrdered THEN crt.Quantity - crt.QuantitySold
                ELSE crt.QuantityOrdered - prev.RunningTotal
            END QuantitySoldNew
            ,CASE 
                WHEN prev.RunningTotal + (crt.Quantity - crt.QuantitySold) < crt.QuantityOrdered THEN prev.RunningTotal + (crt.Quantity - crt.QuantitySold)
                ELSE crt.QuantityOrdered
            END RunningTotal
    FROM    CteRecursive prev
    INNER JOIN CteRowNumber crt ON prev.Account = crt.Account 
    AND     prev.Item = crt.Item 
    AND     prev.RowNumber + 1 = crt.RowNumber
    WHERE   prev.RunningTotal  < crt.QuantityOrdered
)
SELECT   cte.ID
        ,cte.Account
        ,cte.Item
        ,cte.QuantitySoldNew
FROM    CteRecursive cte;
--or CteRecursive can be used to update QuantitySold column from [dbo].[myInventory] table
--UPDATE    myInventory 
--SET       QuantitySold = inv.QuantitySold + cte.QuantitySoldNew
--FROM  myInventory inv
--INNER JOIN CteRecursive cte ON inv.ID = cte.ID;