显示一组记录中的多个列

时间:2014-08-31 05:41:33

标签: sql postgresql multiple-columns aggregation crosstab

鉴于表格:

score | name | time | nick
1       'A'    1      'X' 
4       'A'    2      'X'
10      'A'    3      'X'
10      'A'    4      'X'
1       'A'    5      'X'
1       'B'    6      'Z' 
4       'C'    7      'Z'

我想创建一个多列的输出,第一个是得分,其他总和(时间)为name||'_time_'::text||nick。< / p>

所以它会是:

score | A_time_X | B_time_Z
1       6          0
4       2          0
10      7          0
1       0          6  
4       0          7

每个分数的列显示GROUP (score,name,nick)相同的时间总和。将为nick的其他值显示更多列。

这可能吗?

2 个答案:

答案 0 :(得分:2)

group by部分很容易。之后,您正在转移A_time_XB_time_Z。一种转向方式是case构造:

select  score
,       coalesce(case when name = 'A' and nick = 'X' then sum(time) end,0) as A_time_X
,       coalesce(case when name = 'B' and nick = 'Z' then sum(time) end,0) as B_time_Z
from    Table1
group by
        score
,       name
,       nick

Working example at SQL Fiddle.

有关更多旋转选项,请参阅this answer

答案 1 :(得分:0)

穷人与CASE

的关系

我会在子查询中聚合以简化。也可能更快:

SELECT score
     , CASE WHEN name = 'A' AND nick = 'X' THEN sum_time ELSE 0 END AS a_x
     , CASE WHEN name = 'B' AND nick = 'Z' THEN sum_time ELSE 0 END AS b_z
FROM  (
   SELECT score, name, nick, COALESCE(sum(time), 0) AS sum_time
   FROM   table1
   GROUP  BY 1,2,3
   ) sub
ORDER  BY score, name, nick;

crosstab()

首先阅读基本说明:

由于crosstab()需要,因此请从(name, nick)的组合生成唯一键:

SELECT * FROM crosstab(
   $$
   SELECT score
        , CASE WHEN name = 'A' AND nick = 'X' THEN 1
               WHEN name = 'B' AND nick = 'Z' THEN 2 END AS key
        , COALESCE(sum(time), 0) AS val
   FROM   table1
   WHERE (name = 'A' AND nick = 'X' OR
          name = 'B' AND nick = 'Z')   -- exclude rest (optional, faster)
   GROUP  BY name, nick, score
   ORDER  BY key, score;  -- (!) reversed order to get your untypical result
   $$
  ,'VALUES (1),(2)'       -- match key values in order
  ) AS t (score int, a_x int, b_z int);

生成结果(最后一行中的错误除外) 但是,通常情况下,您需要:

   ORDER  BY score, key;  -- (!) typical case

要获得此结果(一行中相同分数的所有值):

score | A_time_X | B_time_Z
1       6          6
4       2          7
10      7          NULL

SQL Fiddle没有crosstab(),因为目前无法在那里安装其他模块。

动态查询?

很难得到,as @Andomar already comemnted。在这里查看可能的内容: