条件:PostgreSQL 8.4(这对于9.x来说太简单了)
表:
id | gpa | class | rank
----+-----+---------+--------
1 | 2.0 | english | low
1 | 2.0 | math | low
1 | 2.0 | pe | low
1 | 2.0 | spanish | medium
2 | 3.5 | english | high
2 | 3.5 | history | high
2 | 3.5 | art | great
2 | 3.5 | tech | high
3 | 4.0 | pe | medium
3 | 4.0 | spanish | high
3 | 4.0 | english | great
3 | 4.0 | art | great
通缉:
id | gpa | great | high | medium | low
----+-----+--------------+------------------------+---------+-----
1 | 2.0 | | | spanish | english, math, pe
2 | 3.5 | art | english, history, tech | |
3 | 4.0 | art, english | spanish | pe |
当前方法:
WITH details AS (
select * from table order by rank, class
)
SELECT id
, gpa
, array_to_string(array_agg(CASE WHEN rank='great' THEN class END,', ')) as great
, array_to_string(array_agg(CASE WHEN rank='high' THEN class END,', ')) as high
, array_to_string(array_agg(CASE WHEN rank='medium' THEN class END,', ')) as medium
, array_to_string(array_agg(CASE WHEN rank='low' THEN class END,', ')) as low
FROM details
ORDER BY gpa;
所以我试着把它作为我正在做的一个例子 - 不,我没有一个具有这种结构的实际表没有太多标准化,但我确实有一个子查询产生这样的东西。
实际上我的array_agg()也是连接两个字段(一个单词和一个数字),我按数字排序,例如。(array_agg(CASE ... THEN foo || ' - ' || bar
),不幸的是我的输出只是大部分排序。如果我有更多时间,也许我可以改善这个问题。
答案 0 :(得分:1)
创建一个类似的函数:
create or replace function sort(anyarray) returns anyarray language sql as
$$
select array_agg(x) from(
select unnest($1) as x order by 1
) tab;
$$;
然后:
...
array_to_string(sort(array_agg(CASE WHEN rank='great' THEN class END,', ')))
...
答案 1 :(得分:1)
执行此查询时:
with details AS (
select * from table order by class
)
select t.id, t.gpa,
(select array_to_string(array_agg(class),',')
from details d
where d.id = t.id and d.gpa = t.gpa and rank = 'great')
as great,
(select array_to_string(array_agg(class),',')
from details d
where d.id = t.id and d.gpa = t.gpa and rank = 'high')
as high,
(select array_to_string(array_agg(class),',')
from details d
where d.id = t.id and d.gpa = t.gpa and rank = 'medium')
as medium,
(select array_to_string(array_agg(class),',')
from details d
where d.id = t.id and d.gpa = t.gpa and rank = 'low')
as low
from table t
group by t.id, t.gpa
order by t.gpa
我得到了结果:
id gpa great high medium low
----+-----+-------------+----------------------+----------+------------------
1 2.0 spanish english,math,pe
2 3.5 art english,history,tech
3 4.0 art,english spanish pe
我希望你能服务。
更新:其他选项,效果更佳。
select t.id, t.gpa,
a.class as great,
b.class as high,
c.class as medium,
d.class as low
from table t
left join (select id, gpa, array_to_string(array_agg(class),',') as class
from table
where rank = 'great'
group by id, gpa
) a on (a.id = t.id and a.gpa = t.gpa)
left join (select id, gpa, array_to_string(array_agg(class),',') as class
from table
where rank = 'high'
group by id, gpa
) b on (b.id = t.id and b.gpa = t.gpa)
left join (select id, gpa, array_to_string(array_agg(class),',') as class
from table
where rank = 'medium'
group by id, gpa
) c on (c.id = t.id and c.gpa = t.gpa)
left join (select id, gpa, array_to_string(array_agg(class),',') as class
from table
where rank = 'low'
group by id, gpa
) d on (d.id = t.id and d.gpa = t.gpa)
group by t.id, t.gpa, a.class, b.class, c.class, d.class
order by t.gpa