MSSQL ERP 数量均摊

MSSQL ERP 数量均摊


先贴上参考学习帖子。感谢前辈的文摘

需求背景

以自己的学习结果做了一个调整,防止有小伙伴看不懂CTE

以销售订单为例

行号 物料编码 数量
1 A001 100
2 A001 200
3 A001 30
4 B001 200
5 B001 280

库存数据

行号 物料编码 库存数量
1 A001 280
2 B001 500

希望看到的结果

行号 物料编码 数量 库存数量
1 A001 100 100
2 A001 200 180
3 A001 30 0
4 B001 200 200
5 B002 280 300

DECLARE @SalOrder TABLE 
(
  FMaterialId NVARCHAR(255),
  FQty  DECIMAL(18,10)
)
 
insert into @SalOrder values
('A001',100),
('A001',200),
('A001',30),
('B001',200),
('B001',280)

DECLARE @StockQty TABLE 
(
  FMaterialId NVARCHAR(255),
  FQty  DECIMAL(18,10)
)
 
insert into @StockQty values
('A001',280),
('B001',500)

-- 先把数据拼接在一起
SELECT 
	ROW_NUMBER() OVER(ORDER BY T.FMaterialId) AS FID
	,ROW_NUMBER() OVER(PARTITION BY T.FMaterialId ORDER BY T.FMaterialId) AS FRow
	,T.FMaterialId '物料ID',T.FQty '订单数量',T1.FQty AS '库存数'
	,CAST(0 AS DECIMAL(18,10)) AS '预留需求汇总数'
	,CAST(0 AS DECIMAL(18,10)) AS '预留计算结存数'
	,CAST(0 AS DECIMAL(18,10)) AS '预留分摊结果'
	INTO #Temp
FROM @SalOrder T
	JOIN @StockQty T1 ON T.FMaterialId = T1.FMaterialId

-- 开始处理汇总数
UPDATE T
	SET T.预留需求汇总数 = (SELECT SUM(X.订单数量) FROM #Temp X WHERE X.物料ID = T.物料ID AND X.FID <= T.FID),
	T.预留计算结存数 = T.库存数 - (SELECT SUM(X.订单数量) FROM #Temp X WHERE X.物料ID = T.物料ID AND X.FID <= T.FID)
FROM #Temp T

-- 初步处理分摊结果
UPDATE T
	SET T.预留分摊结果 = 
		case when T.预留计算结存数 >= 0 then T.订单数量
		   when T.预留计算结存数 <0 and ABS(T.预留计算结存数) <= T.订单数量  then T.订单数量 + T.预留计算结存数
		   when T.预留计算结存数 < 0 and ABS(T.预留计算结存数) > T.订单数量 then 0 END
FROM #Temp T

-- 最终处理,预留剩余的需要加上去,也就是当尾行大于0的时候需要处理
UPDATE T
	SET T.预留分摊结果 = T.预留分摊结果 + T.预留计算结存数
FROM #Temp T
WHERE T.预留计算结存数 >= 0 AND FID = (SELECT MAX(FID) FROM #Temp X WHERE T.物料ID = X.物料ID)

SELECT * FROM #Temp

DROP TABLE #Temp
FID FRow 物料ID 订单数量 库存数 预留需求汇总数 预留计算结存数 预留分摊结果
1 1 A001 100.0000000000 280.0000000000 100.0000000000 180.0000000000 100.0000000000
2 2 A001 200.0000000000 280.0000000000 300.0000000000 -20.0000000000 180.0000000000
3 3 A001 30.0000000000 280.0000000000 330.0000000000 -50.0000000000 0.0000000000
4 1 B001 200.0000000000 500.0000000000 200.0000000000 300.0000000000 200.0000000000
5 2 B001 280.0000000000 500.0000000000 480.0000000000 20.0000000000 300.0000000000

最终的分摊结果与我们希望一致。
PS:测试的时候可以把Update一行行注释来看效果。

20240705换个简单的脚本方案实现。

DECLARE @SalOrder TABLE 
(
  FMaterialId NVARCHAR(255),
  FQty  DECIMAL(18,10)
)
 
insert into @SalOrder values
('A001',100),
('A001',200),
('A001',30),
('B001',200),
('B001',280)

DECLARE @StockQty TABLE 
(
  FMaterialId NVARCHAR(255),
  FQty  DECIMAL(18,10)
)
 
insert into @StockQty values
('A001',280),
('B001',500);

WITH orderDetail AS
(
	SELECT 
		T.*,SUM(T.FQty) OVER(PARTITION BY T.FMaterialId ORDER BY T.FQty) AS FTotalQty,T1.FQty AS 'FStockQty'
	FROM @SalOrder T
		LEFT JOIN @StockQty T1 ON T.FMaterialId = T1.FMaterialId
)
SELECT *
	,CASE WHEN T.FStockQty >= T.FTotalQty THEN 0
		WHEN T.FStockQty < T.FTotalQty AND ABS(T.FStockQty - T.FTotalQty) >= T.FQty THEN T.FQty
		WHEN T.FStockQty < T.FTotalQty AND ABS(T.FStockQty - T.FTotalQty) < T.FQty THEN ABS(T.FStockQty - T.FTotalQty)
		ELSE 0 END AS 'FLackQty'
FROM orderDetail T
posted @ 2022-02-17 11:29  嘿嘿嘿~  阅读(145)  评论(0编辑  收藏  举报