在Oracle中防止运行总数变为负值

时间:2016-11-22 17:23:57

标签: oracle function sum running-total analytical

列'金额'第一行的值为5,第二行的值为-10。

有没有办法让oracle的sum(amount)over()函数为第二行返回0而不是-5?

2 个答案:

答案 0 :(得分:2)

公然使用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(第一次尝试保留为下面的评论引用它)

当数量低于0时,我无法弄清楚如何中断窗口函数将值重置为0 ...所以我使用了一个递归CTE,这让我有了更大的控制权。

如果id不是顺序的,我们可以添加一个row_Number,这样我们就可以加入一个ID ......或者我们可以使用min(),其中&gt; OLDID。我假设我们有一个唯一的密钥唯一ID或某种方式按照您希望总和发生的顺序“排序”记录......

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;

  1. CTE:ARaw只是一个示例数据集
  2. CTE:T添加一个序列行号,因为ID中存在间隙,允许在递归CTE上使用更简单的连接方法。
  3. CTE:CTE是递归CTE,它保持一个运行总计,并有一个case语句,当它低于0时将运行总数重置为0

答案 1 :(得分:1)

您可以使用案例陈述,但这不是真正的总计

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