2017-02-10 1 views
0

Bitte entschuldigen Sie meine nicht sehr propper Weg, dies zu fragen, wie ich bin neu in Postgres ...Postgres - bind Ergebnisse gleicher Art von Jahr - lange breite Daten

die folgenden zwei Tabellen Mit:

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 

Und

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 

ich möchte die folgende Ausgabe (für id <= 2)

0.123.380 erhalten

So type ist die Obermenge aller Typen vorhanden in Tabelle val.
NULL bedeutet, dass es keinen Wert für Label C gibt.
Idealerweise sind die Spaltenüberschriften Jahre der Zeit. Alternativ kann die ID selbst ...

Antwort

1

Existiert mindestens zwei Möglichkeiten, dies zu tun.

Wenn Ihre Tabelle nicht viele Kategorien haben, können Sie CTE verwenden

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 
; 

Aber wenn Sie viele oder dynamische Kategorien haben müssen Sie verwenden Kreuztabellen-:

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); 
; 
Verwandte Themen