鉴于表格:
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
的其他值显示更多列。
这可能吗?
答案 0 :(得分:2)
group by
部分很容易。之后,您正在转移A_time_X
和B_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。在这里查看可能的内容: