如何求和之前的总和,例如 N = (N-1) + (N-2) + ... + 1?

Lua*_*ynh 7 postgresql join

我有一个表名“ TABLE_A ( id integer, no integer) ”。

我想用“id”和当前的“no sum of no”=以前的“no sum of no”对“no”求和

这是我的代码:

1/创建表并插入数据:

create table table_a (id int, no int);

insert into table_a values(1, 10);
insert into table_a values(1, 20);
insert into table_a values(1, 30);
insert into table_a values(2, 100);
insert into table_a values(2, 200);
insert into table_a values(2, 300);
insert into table_a values(3, 1);
insert into table_a values(3, 2);
insert into table_a values(3, 3);
insert into table_a values(3, 3);
Run Code Online (Sandbox Code Playgroud)

2/ 预期结果:

id | sum_of_no
--------------
1  | 60
2  | 660
3  | 669
Run Code Online (Sandbox Code Playgroud)

3/我的解决方案(好的):

with t_report_code_temp as
(   
select id, sum(no) as t_code
from table_a
group by id 
)
select a.id, sum(b.t_code)
from t_report_code_temp a 
join t_report_code_temp b on b.id <= a.id
group by a.id
order by 1
Run Code Online (Sandbox Code Playgroud)

我的问题:

你能给我更好的解决方法吗?

Lua*_*ynh 5

来自 Craig Ringer,ypercube。

这是我的测试:

create table table_a (id int, no int);

insert into table_a  (1)
select a, a
from generate_series(1, 1000000) a
Run Code Online (Sandbox Code Playgroud)

克雷格·林格的询问

with t_report_code_temp(id, t_code) as
(   
select id, sum(no)
from table_a
group by id 
)
SELECT
  id,
  sum(t_code) OVER (ORDER BY id ASC)
FROM t_report_code_temp;

1.000.000 rows -> 5.5s
2.000.000 rows -> 7s   (run (1) twice)
Run Code Online (Sandbox Code Playgroud)

ypercube 的查询

SELECT
  id,
  SUM(SUM(no)) OVER (ORDER BY id ASC) AS sum_of_no
FROM table_a
GROUP BY id ;

1.000.000 rows -> 3.7s
2.000.000 rows -> 5.5s   (run (1) twice)
Run Code Online (Sandbox Code Playgroud)

我看到了窗口函数的神奇之处。谢谢 !


ype*_*eᵀᴹ 3

改进(?)克雷格林格的答案。代码更少,但不确定它是否更具可读性或更令人困惑:

SELECT
  id,
  SUM(SUM(no)) OVER (ORDER BY id ASC) AS sum_of_no
FROM table_a
GROUP BY id 
ORDER BY id ;
Run Code Online (Sandbox Code Playgroud)

在SQL-Fiddle上测试

您的评论是正确的,当窗口函数(或 的聚合OVER())具有时ORDER BY,默认窗口是:ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW它会生成 的运行总计SUM()


执行逻辑流程为:

FROM table_a            -- get all rows of table_a

-- WHERE                -- void here

GROUP BY id             -- make groups of rows, one for each value of "id"
      -- SUM(no) AS y   -- and calculate aggregates, like SUM(no)

-- HAVING               -- void here

SELECT                  -- calculate window functions and window aggregates 
  id,                   -- and any other function used in SELECT or ORDER BY 
  SUM(y) OVER (ORDER BY id ASC) AS sum_of_no

ORDER BY id             -- order the result set
Run Code Online (Sandbox Code Playgroud)