在Postgres中对表执行累积和的最佳方法是什么,以便在将更多字段/列添加到表中时可以带来最佳性能和灵活性。
表格
a b d 1 59 15 181 2 16 268 3 219 4 102
累积
a b d 1 59 15 181 2 31 449 3 668 4 770
答案 0 :(得分:3)
用于运行总和的窗口函数。
SELECT sum(a) OVER (ORDER BY d) as "a",
sum(b) OVER (ORDER BY d) as "b",
sum(d) OVER (ORDER BY d) as "d"
FROM table;
如果您有多个运行总和,请确保订单相同。
重要的是要注意,如果您希望您的列在问题中显示为聚合表(每个字段都是唯一排序的),那么它就会更加复杂。
更新:我已修改查询以执行所需的排序,但没有给定的公共字段。
WITH
rcd AS (
select row_number() OVER() as num,a,b,d
from tbl
),
sorted_a AS (
select row_number() OVER(w1) as num, sum(a) over(w2) a
from tbl
window w1 as (order by a nulls last),
w2 as (order by a nulls first)
),
sorted_b AS (
select row_number() OVER(w1) as num, sum(b) over(w2) b
from tbl
window w1 as (order by b nulls last),
w2 as (order by b nulls first)
),
sorted_d AS (
select row_number() OVER(w1) as num, sum(d) over(w2) d
from tbl
window w1 as (order by d nulls last),
w2 as (order by d nulls first)
)
SELECT sorted_a.a, sorted_b.b, sorted_d.d
FROM rcd
JOIN sorted_a USING(num)
JOIN sorted_b USING(num)
JOIN sorted_d USING(num)
ORDER BY num;
答案 1 :(得分:3)
你可以使用窗口函数,但是你需要额外的逻辑来避免NULL
s的值:
SELECT id,
(case when a is not null then sum(a) OVER (ORDER BY id) end) as a,
(case when b is not null then sum(b) OVER (ORDER BY id) end) as b,
(case when d is not null then sum(d) OVER (ORDER BY id) end) as d
FROM table;
这假定指定排序的第一列称为id
。
答案 2 :(得分:3)
我认为你真正想要的是:
SELECT id
, sum(a) OVER (PARTITION BY a_grp ORDER BY id) as a
, sum(b) OVER (PARTITION BY b_grp ORDER BY id) as b
, sum(d) OVER (PARTITION BY d_grp ORDER BY id) as d
FROM (
SELECT *
, count(a IS NULL OR NULL) OVER (ORDER BY id) as a_grp
, count(b IS NULL OR NULL) OVER (ORDER BY id) as b_grp
, count(d IS NULL OR NULL) OVER (ORDER BY id) as d_grp
FROM tbl
) sub
ORDER BY id;
表达式count(col IS NULL OR NULL) OVER (ORDER BY id)
在子查询a
中为b
,d
和sub
形成连续的非空行组。
在外部查询中,我们运行累积总和每组。 NULL
值构成他们自己的群组并自动保留NULL
。无需额外的CASE
声明。
SQL Fiddle(列a
添加了一些值以证明效果)。