gpt4 book ai didi

sql-server - CTE - 递归更新数量直到消耗总量

转载 作者:行者123 更新时间:2023-12-02 11:20:57 33 4
gpt4 key购买 nike

我一直在研究 CTE,试图确定是否可以使用订单数量递归更新库存数量记录,直到订单数量被消耗。

以下是表格和记录:

CREATE TABLE [dbo].[myOrder](
[Account] [float] NOT NULL,
[Item] [float] NOT NULL,
[Quantity] [float] NOT NULL
) ON [PRIMARY]

insert into dbo.myOrder values (12345, 1, 50)

CREATE TABLE [dbo].[myInventory](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Account] [float] NOT NULL,
[InvDate] [numeric](18, 0) NOT NULL,
[Item] [float] NOT NULL,
[Quantity] [float] NOT NULL,
[QuantitySold] [float] NOT NULL
) ON [PRIMARY]

insert into dbo.myInventory values (12345, 111287, 1, 45, 40)
insert into dbo.myInventory values (12345, 111290, 1, 40, 0)
insert into dbo.myInventory values (12345, 111290, 1, 12, 0)
insert into dbo.myInventory values (12345, 111291, 1, 25, 0)

myOrder 表中的记录表明要为帐户 12345 创建项目 #1、数量 50 的订单:

Account Item Quantity 
------- ---- --------
12345 1 50

库存表显示帐户 12345 手头有大量商品 #1:

ID Account InvDate Item Quantity QuantitySold
-- ------- ------- ---- -------- ------------
1 12345 111287 1 45 40
2 12345 111290 1 40 0
3 12345 111290 1 12 0
4 12345 111291 1 25 0

目标是开始将 50 个订单数量插入库存记录中,直到 50 个全部消耗完。库存记录按 InvDate 列中的值排序。记录 1 有 5 个剩余数量 (45 - 40 = 5),这将使我们还有 45 个可供订单消耗。记录 2 可以消耗 40 个。记录 3 可以消耗最后 5 个。查询完成后,库存记录将如下所示:

ID Account InvDate Item Quantity QuantitySold
-- ------- ------- ---- -------- ------------
1 12345 111287 1 45 45
2 12345 111290 1 40 40
3 12345 111290 1 12 5
4 12345 111291 1 25 0

注意:库存表存储 QuantitySold,而不是 QuantityRemaining,因此您必须进行数学计算(数量 - QuantitySold)来确定每个库存记录的剩余数量。

我对 CTE 几乎毫无进展。我发现了很多进行选择的示例,其中 CTE 有 2 个部分 - 初始化部分和递归部分联合在一起。我可以用光标来写这个,但我认为可以用 CTE 来完成,我想了解如何操作。

如果有人可以确认 CTE 可以做到这一点或解释如何设置 CTE,我将不胜感激。谢谢!

最佳答案

--@inserted 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;

关于sql-server - CTE - 递归更新数量直到消耗总量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7843129/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com