分区组的SQL运行余额计算
Posted
技术标签:
【中文标题】分区组的SQL运行余额计算【英文标题】:SQL running balance calculation for a partition group 【发布时间】:2021-10-18 08:54:24 【问题描述】:我要求将数量限制在一定水平。以下数据已分区,还提供了行号。请参考下面这是表格中的当前数据
但是输出应该是这样的。请参考下文。
目前的卡车容量为 16 个。但是,如果您看到分区级别的总分配数量为 17。所以我们需要在行级别从最终分配数量中动态减去额外的 1 个数量,最好从行号 1..2..3 像这样。我曾尝试使用 while 循环进行总计,但没有运气
到目前为止我所做的尝试
DECLARE @GroupCount INT
SET @GroupCount = (SELECT MAX(PartitionNum) FROM Allocation_Table)
DECLARE @RowCount INT
-- Declare an iterator
DECLARE @I INT,@J int
--Initialize the iterator
SET @I =1
WHILE (@I <= @GroupCount)
BEGIN
SET @RowCount = (SELECT MAX(RowNumber) FROM Allocation_Table WHERE PartitionNum=@I)
DECLARE @BS float=0
SELECT @BS = cast([Remainder Qty to be dropped] as float) FROM Allocation_Table WHERE PartitionNum=@I
SET @J = 1
WHILE (@J <= @RowCount)
BEGIN
--PRINT @I
declare @BV float, @Qty float,@flg bit,@Ibs float, @EV float
SELECT @Qty=[Final Allocation Qty] FROM Allocation_Table WHERE PartitionNum=@I and RowNumber=@J
set @IBS=@BS
SET @BS=case when (@BS>=@Qty) then @BS-@Qty else @BS end
SET @flg=case when (@IBS>=@Qty) then 1 when (@IBS<@Qty) and @IBS>0 then 1 else 0 end
set @BS= case when (@IBS<@Qty) then 0 else @BS end
update Allocation_Table set BS_Cal=@BS ,Flag=@flg WHERE RowNumber = @J and PartitionNum=@I
SET @J = @J + 1
END
SET @I = @I + 1
【问题讨论】:
不幸的是,您不能使用窗口(和分区)聚合进行这种聚合,您需要使用迭代;最有可能患有 rCTE。 根据问题指南,请不要发布代码、数据、错误消息等的图像 - 将文本复制或键入问题中。请保留将图像用于图表或演示渲染错误,无法通过文本准确描述的事情。 您最初是如何得到Final Allocation Qty
的4,9,4
的?为什么不先把它改正,而不是以后再做修复
@Squirrel - 不幸的是,这首先无法纠正。该数量是系统建议的。但我们需要根据卡车容量限制它
@DaleK 发布了我目前尝试过的代码
【参考方案1】:
与 cmets 中所说的相反,这很可能使用窗口函数,只是有点复杂。
假设我正确理解了您的情况,您希望按照 RowNumber
的顺序从 material
中删除项目,直到到达 Truck capacity
。为此,只需要基于上一行中的值进行一些运行聚合和条件数学:
查询
declare @t table(pn int,rn int,Material varchar(100),Allocation int,Capacity int);
insert into @t values
(1,1,'abc',4,16)
,(1,2,'bac',9,16)
,(1,3,'cab',4,16)
,(2,1,'abc',4,12)
,(2,2,'bac',9,12)
,(2,3,'cab',4,12)
,(3,1,'abc',4,2)
,(3,2,'bac',9,2)
,(3,3,'cab',4,2)
,(4,1,'abc',14,112)
,(4,2,'bac',19,112)
,(4,3,'cab',14,112)
,(5,1,'abc',140,112)
,(5,2,'bac',19,112)
,(5,3,'cab',14,112)
;
with d as
(
select *
,sum(Allocation) over (partition by pn) as TotalAllocation
,sum(Allocation) over (partition by pn) - Capacity as TotalOverage
,sum(Allocation) over (partition by pn)
- Capacity
- sum(Allocation) over (partition by pn order by rn)
as Overage
from @t
)
select pn
,rn
,Material
,Capacity
,TotalAllocation
,Allocation
,case when Overage > 0
then 0
else case when lag(Overage,1) over (partition by pn order by rn) is null
then case when Allocation < (Allocation - TotalOverage)
then Allocation
else Allocation - TotalOverage
end
else
case when lag(Overage,1,0) over (partition by pn order by rn) > 0
then Allocation - lag(Overage,1,0) over (partition by pn order by rn)
else Allocation
end
end
end as AdjustedAllocation
from d
order by pn
,rn;
输出
pn | rn | Material | Capacity | TotalAllocation | Allocation | AdjustedAllocation |
---|---|---|---|---|---|---|
1 | 1 | abc | 16 | 17 | 4 | 3 |
1 | 2 | bac | 16 | 17 | 9 | 9 |
1 | 3 | cab | 16 | 17 | 4 | 4 |
2 | 1 | abc | 12 | 17 | 4 | 0 |
2 | 2 | bac | 12 | 17 | 9 | 8 |
2 | 3 | cab | 12 | 17 | 4 | 4 |
3 | 1 | abc | 2 | 17 | 4 | 0 |
3 | 2 | bac | 2 | 17 | 9 | 0 |
3 | 3 | cab | 2 | 17 | 4 | 2 |
4 | 1 | abc | 112 | 47 | 14 | 14 |
4 | 2 | bac | 112 | 47 | 19 | 19 |
4 | 3 | cab | 112 | 47 | 14 | 14 |
5 | 1 | abc | 112 | 173 | 140 | 79 |
5 | 2 | bac | 112 | 173 | 19 | 19 |
5 | 3 | cab | 112 | 173 | 14 | 14 |
【讨论】:
谢谢你的好先生@imdave 这工作得很好。非常感谢以上是关于分区组的SQL运行余额计算的主要内容,如果未能解决你的问题,请参考以下文章