Oracle SQL在字段更改时运行总计(仅当字段更改时,列上的SUM)

时间:2018-01-17 20:24:36

标签: sql oracle

我有一个关于如何仅在字段发生变化时对列进行SUM的问题。

以下表为例:

请注意,A列和B列是不同的表。即A选自表X,B选自表Y

  

选择X.A,Y.B
  来自X
  INNER JOIN Y ON X.DATE = Y.DATE AND X.VAL1 =   Y.VAL1和X.VAL2 = Y.VAL2

 A     B
123    5
123    5
456    10
789    15
789    15

我需要在A列的字段更改中对B列求和:

即。查询应返回 5 + 10 + 15 = 30 (第一次为5,因为A列中的值为123,第二次为10,因为A列从123更改为456 - 请注意第二行是跳过,因为列A仍然包含值123 - 因此字段逻辑的更改等等。

我无法做一个简单的SUM(B),因为它会返回 50 。我也做不到SUM(B) OVER (PARTITION BY A)因为那会按小组进行总计,而不是通过改变字段。

我的输出需要如下所示:

A    B    X
123  5    5
123  5    5
456  10   15
789  15   30
789  15   30

我试图在一个简单的查询中执行此操作。我可以使用特定功能来执行此操作吗?

3 个答案:

答案 0 :(得分:0)

对于提供的简单数据集,以下内容应该有效。当然,您希望在确切的用例中查看ORDER BY条款的正确性。

SELECT a
      ,b
      ,SUM(CASE WHEN a = prev_a THEN 0 ELSE b END) OVER (ORDER BY a RANGE UNBOUNDED PRECEDING) AS x
  FROM (
SELECT a
      ,b
      ,LAG(a) OVER (ORDER BY a) AS prev_a
  FROM {your_query}
  )

此解决方案使用LAG函数,该函数返回先前结果中的指定列。然后外部查询的SUM仅在前一行没有相同值时才给出值。 SUM中还涉及窗口条款,因为您指定需要运行总计。

答案 1 :(得分:0)

钽daaa?

SQL> with test (a, b) as
  2  (select 123, 5 from dual union all
  3   select 123, 5 from dual union all
  4   select 456, 10 from dual union all
  5   select 789, 15 from dual union all
  6   select 789, 15 from dual
  7  ),
  8  proba as(
  9  select a, b,
 10    case when a <> nvl(lag(a) over (order by a), 0) then 'Y' else 'N' end switch
 11  from test
 12  )
 13  select a, b,
 14    sum(decode(switch, 'Y', b, 0)) over (partition by null order by a) x
 15  from proba
 16  order by a;

         A          B          X
---------- ---------- ----------
       123          5          5
       123          5          5
       456         10         15
       789         15         30
       789         15         30

SQL>

答案 2 :(得分:0)

你也可以创建一个函数并使用它,见下面的示例,

create package test_pkg123
as
  a number;
  r_sum NUMBER;
  function get_r_sum(p_a number, p_val NUMBER, rown NUMBER) return number;
end;
/

create or replace package body test_pkg123
as
function get_r_sum(p_a number, p_val NUMBER, rown NUMBER) return number
  is
  begin
      if rown = 1 then
          r_sum := p_val;
          return r_sum;
      end if;
      if p_a != a then
         r_sum := nvl(r_sum, 0) + nvl(p_val, 0);
      end if;
      a := p_a;
      return r_sum;
  end;
end;
/

with test (a, b) as
    (select 123, 5 from dual union all
     select 123, 5 from dual union all
     select 456, 10 from dual union all
     select 789, 15 from dual union all
     select 789, 15 from dual union all
     select 789, 15 from dual union all
     select 123, 2 from dual
    )
select a, b, test_pkg123.get_r_sum(a, b, rownum) r_sum 
  from test;

输出:

     A          B      R_SUM
   123          5          5
   123          5          5
   456         10         15
   789         15         30
   789         15         30
   789         15         30
   123          2         32

选择7行