分区组的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 Qty4,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运行余额计算的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 运行总计算列消息

运行余额的sql查询

SQL窗口函数和运行总计

如何在 R 中使用 dplyr mutate 函数来计算运行余额?

在mysql select查询和查看中计算运行余额

sql server 分区