在PostgreSQL中显示一行中的多个列值

时间:2011-10-26 14:48:47

标签: sql postgresql pivot crosstab

我有这样的查询:

select to_date(to_char(registime, 'YYYY-MM'),'YYYY-MM') as dt,count(id) as total_call  
from all_info 
where alarm_id is null
group by dt   
order by dt

结果就像这样:

dt          total_call      
2011-03-01     45
2011-04-01     61
2011-05-01     62
2011-06-01     41
2011-07-01     48
2011-08-01     42
2011-09-01     28
2011-10-01     39

我希望结果如下面的演示,表格形式:

2011-03-01   2011-04-01  2011-05-01  2011-06-01  ..........
   45            61          62          41

我想使用交叉表,但它似乎不起作用?

1 个答案:

答案 0 :(得分:3)

查看contrib模块 tablefunc 。它提供了您正在寻找的枢轴表功能。 请参阅manual here

关注installation instructions here或@Paul Tomblin在上述评论中提出的文章。

然后你的功能看起来像这样:

SELECT *
  FROM crosstab($$
SELECT 'total_calls'::text AS col_name
      ,to_char(registime, '"x"YYYY_MM_01') as dt
      ,count(id) as total_call  
FROM   all_info 
WHERE  alarm_id is null
GROUP  BY dt   
ORDER  BY dt
$$)
AS ct(
 call_day text
,x2011_03_01 int8
,x2011_04_01 int8
,x2011_05_01 int8
,x2011_06_01 int8
,x2011_07_01 int8
,x2011_08_01 int8
,x2011_09_01 int8
,x2011_10_01 int8);

输出:

  call_day   | x2011_03_01 | x2011_04_01 | x2011_05_01 | x2011_06_01 | x2011_07_01 | x2011_08_01 | x2011_09_01 | x2011_10_01
-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------
 total_calls |           1 |           4 |           4 |           2 |           1 |           5 |           1 |           1

列名不能以数字开头(或者你必须双引号),这就是我用x作为日期前缀的原因。我也简化了你的查询 您可以将其包装在视图或功能中以供重复使用 也许是一个plpgsql函数,可以动态调整列名和EXECUTE。

More details, explanation and links in this related answer