更新行组以从行总和中删除特定的总金额 SQL
Update group of rows to delete a specific total amount from the sum of the rows SQL
在示例中,我想从 Table 2 中 ValueBefore
的总和中减去 TABLE 1
中的 Subtracted
值 GroupID
.从第一行中减去的值,如果有余数,则从组中的下一行中减去(依此类推),直到减去总计。
有没有一种方法可以在不遍历行来获取余数的情况下执行此操作?
我的 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
上按 ID
和 SUM
分组,现在可以计算 运行 总数:
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
我会使用累加和一些相对简单的比较:
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;
在示例中,我想从 Table 2 中 ValueBefore
的总和中减去 TABLE 1
中的 Subtracted
值 GroupID
.从第一行中减去的值,如果有余数,则从组中的下一行中减去(依此类推),直到减去总计。
有没有一种方法可以在不遍历行来获取余数的情况下执行此操作?
我的 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
上按 ID
和 SUM
分组,现在可以计算 运行 总数:
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
我会使用累加和一些相对简单的比较:
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;