简体   繁体   English

如何在PostgreSQL中透视表并获取列和行的总数?

[英]How to pivot table in PostgreSQL and get totals of columns and rows?

Create temporary table 创建临时表

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

Insert data 插入资料

-- 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');

Wanted final result: 想要最终结果:

 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

What have I done so far: 到目前为止,我做了什么:

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;

Returns results as: 返回结果为:

 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
:

Questions: 问题:

  1. How to get total sum of each column and each row? 如何获得每一列和每一行的总和?
  2. How to make a control: if "total sum" of each column (264) is equal to total sum of each row (264) then write 264 (please look at the wanted final result above), otherwise write "R". 如何进行控制:如果每列(264)的“总和”等于每行(264)的总和,则编写264(请看上面想要的最终结果),否则写“ R”。

Edit 编辑

Based on @Gordon Linoff answer I made query: 基于@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;

Returned result: 返回结果:

 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

This is actually a combination of several things: 这实际上是几件事的组合:

  • The right group by clause. 正确的group by子句。
  • Conditional aggregation 条件聚合
  • Rollup (which is available in the current release, 9.5) 汇总(在当前版本9.5中可用)

The SQL query looks like: 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM