防止 运行 total 在 Oracle 中变为负数
Preventing running total from going negative in Oracle
第 'amount' 列第一行的值为 5,第二行的值为 -10。
有没有办法让 oracle 的 sum(amount) over() 函数在第二行中变成 return 0 而不是 -5?
您可以使用 case 语句,但这不是真的 运行 总计
with t as (
select 5 as x, 1 as id from dual
union all
select -10, 2 as id from dual
union all
select 20, 3 as id from dual
union all
select 30, 4 as id from dual
union all
select 10, 5 as id from dual
)
select t.x,
case when sum(x) over (order by id) < 0 then 0
else sum(x) over (order by id)
end running_total
from t
order by id;
X RUNNING_TOTAL
5 5
-10 0
20 15
30 45
10 55
公然使用 Rajesh Chamarthi 的示例来源:但进行更改以显示更多的负数和正数...并展示案例如何将所有负数更改为零,同时保持其他数量...
with t as (
select 5 as x, 1 as id from dual
union all
select -10, 2 as id from dual
union all
select 7, 3 as id from dual
union all
select -5, 4 as id from dual
union all
select -2, 5 as id from dual
),
B as (select t.x,
case when sum(x) over (order by id) < 0 then 0
else sum(x) over (order by id)
end Amount
from t
order by id)
Select X, Case when amount < 0 then 0 else amount end as Amount from B;
T Amount
5 5
-10 0
7 2
-5 0
-2 0
----尝试 2(第一次尝试保留为下面的注释引用)
我无法弄清楚如何中断 window 函数以在金额低于 0 时将值重置为 0...所以我使用了递归 CTE,这给了我更大的控制权。
如果 ID 不是连续的,我们可以添加一个 row_Number,这样我们就有一个 ID 可以加入...或者我们可以使用 min() where > oldID。我假设我们有一个单一的键唯一 ID 或某种方式 "Sorting" 按您希望总和发生的顺序记录的方式...
with aRaw as (
select 5 as x, 15 as id from dual
union all
select -10, 20 as id from dual
union all
select 7, 32 as id from dual
union all
select 2, 46 as id from dual
union all
select -15, 55 as id from dual
union all
select 3, 68 as id from dual
),
t as (Select A.*, Row_number() over (order by ID) rn from aRAW A),
CTE(RN, ID, x, SumX) AS (
Select T.RN, T.ID, x, X from t WHERE ID = (Select min(ID) from t)
UNION ALL
Select T.RN, T.ID, T.X, case when T.X+CTE.SumX < 0 then 0 else T.X+Cte.sumX end from T
INNER JOIN CTE
on CTE.RN+1=T.RN)
Select * from cte;
.
- CTE:ARaw只是一个样本数据集
- CTE:T 添加一个连续的行号,以防 ID 中存在间隙,从而允许在递归 CTE 上使用更简单的连接方法。
- CTE:CTE 是递归 CTE,它保持 运行 总数,并且有一个 case 语句在低于 0
时将 运行 总数重置为 0
第 'amount' 列第一行的值为 5,第二行的值为 -10。
有没有办法让 oracle 的 sum(amount) over() 函数在第二行中变成 return 0 而不是 -5?
您可以使用 case 语句,但这不是真的 运行 总计
with t as (
select 5 as x, 1 as id from dual
union all
select -10, 2 as id from dual
union all
select 20, 3 as id from dual
union all
select 30, 4 as id from dual
union all
select 10, 5 as id from dual
)
select t.x,
case when sum(x) over (order by id) < 0 then 0
else sum(x) over (order by id)
end running_total
from t
order by id;
X RUNNING_TOTAL
5 5
-10 0
20 15
30 45
10 55
公然使用 Rajesh Chamarthi 的示例来源:但进行更改以显示更多的负数和正数...并展示案例如何将所有负数更改为零,同时保持其他数量...
with t as (
select 5 as x, 1 as id from dual
union all
select -10, 2 as id from dual
union all
select 7, 3 as id from dual
union all
select -5, 4 as id from dual
union all
select -2, 5 as id from dual
),
B as (select t.x,
case when sum(x) over (order by id) < 0 then 0
else sum(x) over (order by id)
end Amount
from t
order by id)
Select X, Case when amount < 0 then 0 else amount end as Amount from B;
T Amount
5 5
-10 0
7 2
-5 0
-2 0
----尝试 2(第一次尝试保留为下面的注释引用)
我无法弄清楚如何中断 window 函数以在金额低于 0 时将值重置为 0...所以我使用了递归 CTE,这给了我更大的控制权。
如果 ID 不是连续的,我们可以添加一个 row_Number,这样我们就有一个 ID 可以加入...或者我们可以使用 min() where > oldID。我假设我们有一个单一的键唯一 ID 或某种方式 "Sorting" 按您希望总和发生的顺序记录的方式...
with aRaw as (
select 5 as x, 15 as id from dual
union all
select -10, 20 as id from dual
union all
select 7, 32 as id from dual
union all
select 2, 46 as id from dual
union all
select -15, 55 as id from dual
union all
select 3, 68 as id from dual
),
t as (Select A.*, Row_number() over (order by ID) rn from aRAW A),
CTE(RN, ID, x, SumX) AS (
Select T.RN, T.ID, x, X from t WHERE ID = (Select min(ID) from t)
UNION ALL
Select T.RN, T.ID, T.X, case when T.X+CTE.SumX < 0 then 0 else T.X+Cte.sumX end from T
INNER JOIN CTE
on CTE.RN+1=T.RN)
Select * from cte;
.
- CTE:ARaw只是一个样本数据集
- CTE:T 添加一个连续的行号,以防 ID 中存在间隙,从而允许在递归 CTE 上使用更简单的连接方法。
- CTE:CTE 是递归 CTE,它保持 运行 总数,并且有一个 case 语句在低于 0 时将 运行 总数重置为 0