更新行组以从行总和中删除特定的总金额 SQL

Update group of rows to delete a specific total amount from the sum of the rows SQL

在示例中,我想从 Table 2 中 ValueBefore 的总和中减去 TABLE 1 中的 SubtractedGroupID .从第一行中减去的值,如果有余数,则从组中的下一行中减去(依此类推),直到减去总计。

有没有一种方法可以在不遍历行来获取余数的情况下执行此操作?

我的 table 1:

TABLE 1 of subtracting value
GroupID    Subtracted
  1          32
  2          30

我的 table 2:

ID   GroupID     ValueBefore     Reduction      ValueAfter   
 1     1             10            -10             0
 2     1             15            -15             0 
 3     1              5             -5             0 
 4     1              5             -2             3
 5     2             40            -30            10
 6     2             30              0            30

一种方法是使用 LEFT JOIN 来计算 ValueBefore 的总计 运行。

这个查询:

SELECT t2.ID, t2.GroupID, t2.ValueBefore, r.ValueBefore AS rValueBefore       
FROM Table2 AS t2
LEFT JOIN Table2 AS r 
   ON t2.GroupID = r.GroupID AND t2.ID >= r.ID
ORDER BY t2.ID, r.ID

产生这个输出:

ID  GroupID ValueBefore rValueBefore
------------------------------------
1   1       10          10
2   1       15          10
2   1       15          15
3   1       5           10
3   1       5           15
3   1       5           5
4   1       5           10
4   1       5           15
4   1       5           5
4   1       5           5
5   2       40          40
6   2       30          40
6   2       30          30

如果您在 rValueBefore 上按 IDSUM 分组,现在可以计算 运行 总数:

SELECT t2.ID, t2.GroupID, t2.ValueBefore, SUM(r.ValueBefore) AS Total      
FROM Table2 AS t2
LEFT JOIN Table2 AS r 
   ON t2.GroupID = r.GroupID AND t2.ID >= r.ID  
GROUP BY t2.ID, t2.GroupID, t2.ValueBefore 

输出:

ID  GroupID ValueBefore Total
-----------------------------
1   1       10          10
2   1       15          25
3   1       5           30
4   1       5           35
5   2       40          40
6   2       30          70    

您现在可以使用以下方法计算 ValueAfter

SELECT t.ID, t.GroupID, t.ValueBefore, Total,
       Subtracted,
       CASE 
          WHEN Total - t1.Subtracted  < 0 THEN 0 
          ELSE Total - t1.Subtracted
       END AS ValueAfter
FROM 
(
   SELECT t2.ID, t2.GroupID, t2.ValueBefore, SUM(r.ValueBefore) AS Total      
   FROM Table2 AS t2
   LEFT JOIN Table2 AS r 
      ON t2.GroupID = r.GroupID AND t2.ID >= r.ID  
   GROUP BY t2.ID, t2.GroupID, t2.ValueBefore
) as t
JOIN Table1 AS t1 ON t.GroupID = t1.GroupID
ORDER BY ID

输出:

ID  GroupID ValueBefore Total   Subtracted  ValueAfter
------------------------------------------------------- 
1   1       10          10      32          0
2   1       15          25      32          0
3   1       5           30      32          0
4   1       5           35      32          3
5   2       40          40      30          10
6   2       30          70      30          40

Demo here

我会使用累加和一些相对简单的比较:

select t2.*,
       (case when t2.running_value - t2.valuebefore < t1.subtracted
             then 0
             when t2.running_value < t1.subtracted
             then t2.running_value - t1.subtracted
             else t2.valuebefore
        end) as reduction,
       (case when t2.running_value < t1.subtracted then 0
             else t2.running_value - t1.subtracted
        end) as ValueAfter
from (select t2.*,
             sum(valuebefore) over (partition by groupid order by id) as running_value
      from t2
     ) t2 join
     t1
     on t2.groupid = t1.groupid;