条件: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
),不幸的是我的输出只是大部分排序。如果我有更多时间,也许我可以改进这个问题。
最佳答案
当我执行此查询时:
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
关于arrays - PostgreSQL:对具有不同条件的多个 array_agg() 进行排序的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9241286/