Postgres - 将相同类型的结果按年份绑定到宽数据

时间:2017-02-10 00:15:47

标签: postgresql pivot-table

请原谅我不是很正式的问这个问题,因为我是postgres的新手...

有以下两个表:

CREATE TABLE pub (
   id int
 , time timestamp
);

     id                time
1     1 2010-02-10 01:00:00
2     2 2011-02-10 01:00:00
3     3 2012-02-10 01:00:00

并且

CREATE TABLE val (
   id int
 , type text
 , val int
);

     id  type   val
1     1     A     1
2     1     B     2
3     1     C     3
4     2     A     4
5     2     B     5
6     3     D     6

我想获得以下输出(对于id <= 2

   type   2010   2011
1     A      1      4
2     B      2      5
3     C      3   NULL

因此type是表 val 中所有类型的超集。
NULL表示标签C没有值。
理想情况下,列标题是多年的时间。或者id本身......

1 个答案:

答案 0 :(得分:1)

至少有两种方法可以做到这一点。

如果您的表格类别不多,则可以使用CTE

WITH x AS (
    SELECT type,
           sum(val) FILTER (WHERE date_part('year', time) = 2010) AS "2010",
           sum(val) FILTER (WHERE date_part('year', time) = 2011) AS "2011"
    FROM pub AS p JOIN val AS v ON (v.id = p.id)
    GROUP BY type
) 
SELECT * FROM x
WHERE "2010" is NOT NULL OR "2011" IS NOT NULL
ORDER BY type
;

但是如果您有许多或动态类别,则必须使用交叉表:

CREATE EXTENSION tablefunc;

SELECT * FROM crosstab(
     $$
         SELECT type,
                date_part('year', time)::text as time,
                sum(val) AS val
           FROM pub AS p JOIN val AS v ON (v.id = p.id)
       GROUP BY type, 2 
       ORDER BY 1, 2
     $$,
     $$VALUES ('2010'::text), ('2011'), ('2012') $$
     ) AS ct (type text, "2010" int, "2011" int, "2012" int);
;