2

条件: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() 也连接了两个字段(一个单词和一个数字)并且我按数字 eg( array_agg(CASE ... THEN foo || ' - ' || bar) 排序,不幸的是我的输出只是大部分排序。如果我有更多时间,也许我可以改进这个问题。

4

2 回答 2

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,', '))) 
...
于 2012-02-12T01:25:24.017 回答
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
于 2012-02-12T12:36:14.783 回答