我有一个关于如何仅在字段发生变化时对列进行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
我试图在一个简单的查询中执行此操作。我可以使用特定功能来执行此操作吗?
答案 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行