PostgreSQL - 让第一行显示为其他行的总和

11

有没有办法使第一行与其余行不同,以便它显示相应列的总和?

例如:

      fruits|a|b|c
       total|3|4|6
      apples|1|2|3
     bananas|1|1|2
     oranges|1|1|1

这样的查询是否可行,或者它是否违反了 SQL 的逻辑?它可能是这样的(现在先忽略第一行):

SELECT fruits, sum(a), sum(b), sum(c)
FROM basket

那么第一行将会不同,它将显示单词“总计”而不是水果名称,并显示a(1+1+1=3)、b(2+1+1=4)和c(3+2+1=6)的总和。这样做是否可能?谢谢。


你可以简单地使用 UNION ALL 连接这两个查询(可能还需要转换你的值)。 - dezso
可能是重复的问题:Postgres:选择值的总和,然后再次求和 - Nick Roz
3个回答

26

你可以通过使用CTE来避免对表进行第二次完整扫描:

PostgreSQL 9.2 Schema

create table basket(fruits text, a integer, b integer, c integer);
insert into basket(fruits, a, b, c) values('apples', 1, 1, 1),
                                          ('apples', 0, 1, 2),
                                          ('bananas', 1, 1, 2),
                                          ('oranges', 1, 1, 1);

查询:

with w as ( select fruits, sum(a) a, sum(b) b, sum(c) c
            from basket
            group by fruits )
select * from w union all select 'total', sum(a), sum(b), sum(c) from w

结果:

|  FRUITS | A | B | C |
-----------------------
| bananas | 1 | 1 | 2 |
| oranges | 1 | 1 | 1 |
|  apples | 1 | 2 | 3 |
|   total | 3 | 4 | 6 |

SQL Fiddle 在这里


谢谢。这个更好。 - Andrius
谢谢。我喜欢Postgres,但这个问题让我希望有“rollup”,它是一种更自然的解决方法。rollup - user533832

13

现在,在Postgres的9.5版本中可以实现这一点

PostgreSQL 9.5架构

CREATE TABLE basket(fruits text, a integer, b integer, c integer);
CREATE TABLE
INSERT INTO basket(fruits, a, b, c) values('apples', 1, 1, 1),
                                      ('apples', 0, 1, 2),
                                      ('bananas', 1, 1, 2),
                                      ('oranges', 1, 1, 1);

查询

SELECT coalesce(fruits,'total'), sum(a) a, sum(b) b, sum(c) c
FROM basket
GROUP BY ROLLUP((fruits))

结果

 fruits  | a | b | c
---------+---+---+---
 apples  | 1 | 2 | 3
 bananas | 1 | 1 | 2
 oranges | 1 | 1 | 1
 total   | 3 | 4 | 6

使用ROLLUP与使用带有表达式的GROUPING SETS等效:

SELECT fruits, sum(a) a, sum(b) b, sum(c) c
FROM basket
GROUP BY GROUPING SETS (fruits, ())

GROUPING SETS 中的每个子列表被解释为如果它直接出现在 GROUP BY 子句中一样。


6
SELECT 'total' AS fruits, sum(a), sum(b), sum(c) FROM basket
UNION ALL
SELECT fruits, sum(a), sum(b), sum(c) FROM basket GROUP BY fruits

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接