簡體   English   中英

在Postgres的許多列中添加累計總和

[英]Add cumulative total sum over many columns in Postgres

我的桌子是這樣的:

+----+--------+--------+--------+---------+
| id | type   | c1     | c2     | c3      |
+----+--------+--------+--------+---------+
| a  |      0 | 10     |     10 | 10      |
| a  |      0 | 0      |     10 |         |
| a  |      0 | 50     |     10 |         |
| c  |      0 |        |     10 | 20      |
| c  |      0 |        |     10 |         |
+----+--------+--------+--------+---------+

我需要這樣的輸出:

+----+---------+--------+--------+---------+
| id | type    | c1     | c2     | c3      |
+----+---------+--------+--------+---------+
| a  |       0 | 10     |     10 | 10      |
| a  |       0 | 0      |     10 |         |
| a  |       0 | 50     |     10 |         |
| c  |       0 |        |     10 | 20      |
| c  |       0 |        |     10 |         |
+----+---------+--------+--------+---------+
|total |     0 | 60     |     50 |  30     |
+------------------------------------------+
|cumulative| 0 | 60     |   110  | 140     |
+------------------------------------------+

到目前為止我的查詢:

WITH res_1 AS 
  (SELECT id,c1,c3,c3 FROM cloud10k.dash_reportcard),
  res_2 AS 
  (SELECT 'TOTAL'::VARCHAR, SUM(c1),SUM(c2),SUM(c3) FROM cloud10k.dash_reportcard)       
SELECT * FROM res_1
UNION ALL 
SELECT * FROM res_2;

它產生每列總計
如何將累計總和相加

注意:該演示有3個數據列,我的實際表有250多個。

一遍又一遍地列出250列以獲得列的總和將是非常乏味的,並且效率越來越低-這是一個O(n²)變相的問題。 實際上,您希望等效於窗口函數的方法來計算而不是的運行總計。

您可以:

  1. 將行轉換為一個集合(“ counter-pivot”)。
  2. 運行窗口聚合函數sum() OVER (...)
  3. 將集合轉換回一行(“樞軸”)。

WITH total AS (
  SELECT 'total'::text AS id, 0 AS type
       , sum(c1) AS s1, sum(c2) AS s2, sum(c3) AS s3  -- more ...
  FROM   cloud10k.dash_reportcard
  )
TABLE cloud10k.dash_reportcard

UNION ALL  
TABLE total

UNION ALL
SELECT 'cumulative', 0, a[1], a[2], a[3]  -- more ...
FROM  (
   SELECT ARRAY(
      SELECT sum(v.s) OVER (ORDER BY rn)
      FROM   total
           , LATERAL (VALUES (1, s1), (2, s2), (3, s3)) v(rn, s)  -- more ...
      )::int[] AS a
   ) sub;

LATERAL要求Postgres 9.3+。

dba.SE的相關答案:

步驟也可以使用tablefunc模塊中的crosstab()完成,但就此簡單而言,將其聚合成一個數組並將每個元素放入一個單獨的列中會更簡單。

Postgres 9.1的替代品

與上述相同,但:

...
UNION ALL
SELECT 'cumulative'::text, 0, a[1], a[2], a[3]  -- more ...
FROM  (
   SELECT ARRAY(
      SELECT sum(v.s) OVER (ORDER BY rn)
      FROM  (
         SELECT row_number() OVER (), s
         FROM   unnest((SELECT ARRAY[s1, s2, s3] FROM total)) s  -- more ...
         ) v(rn, s)
      )::int[] AS a
   ) sub;

考慮:

SQL Fiddle演示了兩者。

只需添加另一個CTE即可獲得累積行:

WITH res_1 AS 
  (SELECT id,c1,c2,c3 
   FROM dash_reportcard),
  res_2 AS 
  (SELECT 'TOTAL'::VARCHAR, SUM(c1) AS sumC1,
          SUM(c2) AS sumC2, SUM(c3) AS sumC3 
   FROM dash_reportcard),
   res_3 AS
   (SELECT 'CUMULATIVE'::VARCHAR, sumC1,
           sumC2+sumC1, sumC1+sumC2+sumC3 
    FROM res_2)
SELECT * FROM res_1
UNION ALL 
SELECT * FROM res_2
UNION ALL 
SELECT * FROM res_3;

在這里演示

WITH total AS (
  SELECT 'TOTAL'::VARCHAR, SUM(c1) AS sumc1, SUM(c2) AS sumc2, SUM(c3) AS sumc3
  FROM cloud10k.dash_reportcard
), cum_total AS (
  SELECT 'CUMULATIVE'::varchar, sumc1, sumc1+sumc2, sumc1+sumc2+sumc3
  FROM total
)
SELECT id, c1, c2, c3 FROM cloud10k.dash_reportcard
UNION ALL 
SELECT * FROM total
UNION ALL
SELECT * FROM cum_total;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM