【问题标题】:How to pivot table in PostgreSQL and get totals of columns and rows?如何在 PostgreSQL 中透视表并获取列和行的总数?
【发布时间】:2016-01-18 15:36:56
【问题描述】:

创建临时表

CREATE TEMPORARY TABLE temperature(
id SERIAL,
date timestamp NOT NULL,
temperature integer NOT NULL
);

插入数据

-- insert this data twice (48 rows)
INSERT INTO temperature(date, temperature) VALUES('2010-01-01','0');
INSERT INTO temperature(date, temperature) VALUES('2010-02-01','1');
INSERT INTO temperature(date, temperature) VALUES('2010-03-01','2');
INSERT INTO temperature(date, temperature) VALUES('2010-04-01','3');
INSERT INTO temperature(date, temperature) VALUES('2010-05-01','4');
INSERT INTO temperature(date, temperature) VALUES('2010-06-01','5');
INSERT INTO temperature(date, temperature) VALUES('2010-07-01','6');
INSERT INTO temperature(date, temperature) VALUES('2010-08-01','7');
INSERT INTO temperature(date, temperature) VALUES('2010-09-01','8');
INSERT INTO temperature(date, temperature) VALUES('2010-10-01','9');
INSERT INTO temperature(date, temperature) VALUES('2010-11-01','10');
INSERT INTO temperature(date, temperature) VALUES('2010-12-01','11');
INSERT INTO temperature(date, temperature) VALUES('2011-01-01','0');
INSERT INTO temperature(date, temperature) VALUES('2011-02-01','1');
INSERT INTO temperature(date, temperature) VALUES('2011-03-01','2');
INSERT INTO temperature(date, temperature) VALUES('2011-04-01','3');
INSERT INTO temperature(date, temperature) VALUES('2011-05-01','4');
INSERT INTO temperature(date, temperature) VALUES('2011-06-01','5');
INSERT INTO temperature(date, temperature) VALUES('2011-07-01','6');
INSERT INTO temperature(date, temperature) VALUES('2011-08-01','7');
INSERT INTO temperature(date, temperature) VALUES('2011-09-01','8');
INSERT INTO temperature(date, temperature) VALUES('2011-10-01','9');
INSERT INTO temperature(date, temperature) VALUES('2011-11-01','10');
INSERT INTO temperature(date, temperature) VALUES('2011-12-01','11');

想要的最终结果:

 year | jan | feb | mar | apr | may | jun | jul | aug | sep | oct | nov | dec | total
------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-------
 2010 |   0 |   2 |   4 |   6 |   8 |  10 |  12 |  14 |  16 |  18 |  20 |  22 |   132
 2011 |   0 |   2 |   4 |   6 |   8 |  10 |  12 |  14 |  16 |  18 |  20 |  22 |   132
------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-------
total |   0 |   4 |   8 |  12 |  16 |  20 |  24 |  28 |  32 |  36 |  40 |  44 |   264

到目前为止我做了什么:

SELECT to_char(date, 'yyyy-mm') AS date,
       SUM(temperature) AS total_temp
FROM temperature
WHERE date >= '2010-01-01' AND date<= '2012-12-31'
GROUP BY to_char(date, 'yyyy-mm')
ORDER BY to_char(date, 'yyyy-mm') ASC;

返回结果为:

 id |        date         | temperature
----+---------------------+-------------
  1 | 2010-01-01 00:00:00 |           0
  2 | 2010-02-01 00:00:00 |           1
  3 | 2010-03-01 00:00:00 |           2
  4 | 2010-04-01 00:00:00 |           3
  5 | 2010-05-01 00:00:00 |           4
  6 | 2010-06-01 00:00:00 |           5
  7 | 2010-07-01 00:00:00 |           6
  8 | 2010-08-01 00:00:00 |           7
  9 | 2010-09-01 00:00:00 |           8
 10 | 2010-10-01 00:00:00 |           9
 11 | 2010-11-01 00:00:00 |          10
 12 | 2010-12-01 00:00:00 |          11
 13 | 2011-01-01 00:00:00 |           0
 14 | 2011-02-01 00:00:00 |           1
 15 | 2011-03-01 00:00:00 |           2
 16 | 2011-04-01 00:00:00 |           3
 17 | 2011-05-01 00:00:00 |           4
 18 | 2011-06-01 00:00:00 |           5
 19 | 2011-07-01 00:00:00 |           6
 20 | 2011-08-01 00:00:00 |           7
 21 | 2011-09-01 00:00:00 |           8
 22 | 2011-10-01 00:00:00 |           9
 23 | 2011-11-01 00:00:00 |          10
 24 | 2011-12-01 00:00:00 |          11
:

问题:

  1. 如何得到每列每行的总和?
  2. 如何进行控件:如果每列的“总和”(264) 等于每行的总和 (264),则写 264(请看上面想要的最终结果),否则写“R” .

编辑

根据@Gordon Linoff 的回答,我提出了疑问:

SELECT to_char(date, 'yyyy') AS year, 
SUM(CASE WHEN to_char(date, 'mm') = '01' THEN temperature ELSE 0 END) AS JAN,
SUM(CASE WHEN to_char(date, 'mm') = '02' THEN temperature ELSE 0 END) AS FEB,
SUM(CASE WHEN to_char(date, 'mm') = '03' THEN temperature ELSE 0 END) AS MAR,
SUM(CASE WHEN to_char(date, 'mm') = '04' THEN temperature ELSE 0 END) AS APR,
SUM(CASE WHEN to_char(date, 'mm') = '05' THEN temperature ELSE 0 END) AS MAY,
SUM(CASE WHEN to_char(date, 'mm') = '06' THEN temperature ELSE 0 END) AS JUN,
SUM(CASE WHEN to_char(date, 'mm') = '07' THEN temperature ELSE 0 END) AS JUL,
SUM(CASE WHEN to_char(date, 'mm') = '08' THEN temperature ELSE 0 END) AS AUG,
SUM(CASE WHEN to_char(date, 'mm') = '09' THEN temperature ELSE 0 END) AS SEP,
SUM(CASE WHEN to_char(date, 'mm') = '10' THEN temperature ELSE 0 END) AS OCT,
SUM(CASE WHEN to_char(date, 'mm') = '11' THEN temperature ELSE 0 END) AS NOV,
SUM(CASE WHEN to_char(date, 'mm') = '12' THEN temperature ELSE 0 END) AS DEC,
SUM(temperature) AS Total
FROM   temperature
WHERE date>= '2010-01-01' AND date<= '2012-12-31' 
GROUP  BY 1;

返回结果:

 year | jan | feb | mar | apr | may | jun | jul | aug | sep | oct | nov | dec | total
------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-------
 2010 |   0 |   2 |   4 |   6 |   8 |  10 |  12 |  14 |  16 |  18 |  20 |  22 |   132
 2011 |   0 |   2 |   4 |   6 |   8 |  10 |  12 |  14 |  16 |  18 |  20 |  22 |   132

【问题讨论】:

    标签: postgresql pivot-table crosstab


    【解决方案1】:

    这实际上是几件事的结合:

    • 正确的group by子句。
    • 条件聚合
    • 汇总(在当前版本 9.5 中可用)

    SQL 查询如下所示:

    SELECT to_char(date, 'yyyy') AS month, 
           SUM(CASE WHEN to_char(date, 'mm') = '01' THEN something ELSE 0 END) AS JAN,
           SUM(CASE WHEN to_char(date, 'mm') = '02' THEN something ELSE 0 END) AS FEB,
           . . .
           SUM(CASE WHEN to_char(date, 'mm') = '12' THEN something ELSE 0 END) AS DEC
    FROM kmi_d 
    WHERE date >= '2010-01-01' AND date <= '2012-12-31' 
    GROUP BY ROLLUP( to_char(date, 'yyyy') )
    ORDER BY to_char(date, 'yyyy') ASC
    

    【讨论】:

    • 嗨!感谢您的及时回复,但是由于我使用的是 PostgreSQL 9.0.23 并且无法升级它,因此此查询返回 SQL 错误:错误:函数汇总(文本)不存在第 20 行:GROUP BY ROLLUP(to_char(datum,' yyyy') ) 提示:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。还有其他建议吗?
    猜你喜欢
    • 2017-07-16
    • 1970-01-01
    • 2014-10-26
    • 1970-01-01
    • 2022-01-23
    • 2012-12-05
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    相关资源
    最近更新 更多