2015-10-03 13 views
5

erwarte ich habe derzeit eine Tabelle m von folgendem Format:Crosstab Funktion in Postgres eine eine Zeile Ausgabe zurückkehrt, wenn ich mehrere Zeilen

id scenario period 1 2 3 4 
2  1   1  1 
2  1   2   1 
2  1   3     1 
2  1   4      1 
2  2   1  1 
2  2   2   1 
2  2   3     1 
2  2   4      1 
2  3   1  1 
2  3   2   1 
2  3   3     1 
2  3   4      1 

:

id scenario period ct 
2  1   1  1 
2  1   2  1 
2  1   3  1 
2  1   4  1 
2  2   1  1 
2  2   2  1 
2  2   3  1 
2  2   4  1 
2  3   1  1 
2  3   2  1 
2  3   3  1 
2  3   4  1 

ich die folgende Tabelle erstellen möchten Die Erweiterung tabellefunc wurde bereits in meiner Postgres-Datenbank erstellt. Ich versuche gerade, die crosstab() Funktion zu verwenden, um den Drehpunkt abzuschließen. Allerdings bin ich einen Tisch zu bekommen, die wie folgt aussieht:

id scenario period 1 2 3 4 
2  1   1  1 1 1 1 

die Abfrage Ich habe versucht:

SELECT * FROM crosstab(
     'SELECT id, scenario, period, ct FROM m 
      ORDER BY 1', 
     'SELECT DISTINCT period FROM m 
      ORDER BY 1') 
AS (id, scenario, period, 1, 2, 3, 4); 
+0

Die von Ihnen eingegebene Abfrage ist schlicht ungültig. (In der Spaltendefinitionsliste fehlen Datentypen). Was ist die eigentliche Abfrage, die Sie versucht haben? –

+0

Mein Datensatz ist viel größer, aber ich wollte ein einfacheres Beispiel zeigen. Ich glaube, die richtigere Abfrage wäre: SELECT * FROM Kreuztabellen- ( \t \t 'SELECT id, Szenario, Zeit, ct VON m \t \t \t ORDER BY 1', \t \t ‚SELECT DISTINCT Zeitraum vom m \t \t \t ORDER BY 1 ') AS (ID int, Szenario int, Periode int, "1" int, "2" int, "3" int, "4" int); –

Antwort

3

Diese Abfrage erzeugt die gewünschte Ausgabe:

SELECT id, scenario, period, p1, p2, p3, p4 -- all except aux column rn 
FROM crosstab(
    'SELECT row_number() OVER (ORDER BY id, scenario, period)::int AS rn 
     , id, scenario, period, period, ct 
    FROM m 
    ORDER BY 1' 
, 'VALUES (1), (2), (3), (4)' 
    ) AS (rn int, id int, scenario int, period int, p1 int, p2 int, p3 int, p4 int); 

Zwei besondere Schwierigkeiten :

  1. Sie haben noch keine einzige eindeutige Spalte für den Zeilenname. Ich verwende row_number(), um den Ersatzschlüssel zu generieren: rn. Ich habe es aus dem äußeren SELECT entfernt, um das gewünschte Ergebnis zu erreichen.
    Die Art und Weise, wie Sie es versucht haben, id wird als row_name und alle Eingabezeilen werden zu einer einzigen Zeile Zeile aggregiert.

  2. Sie wollen zusätzliche Spalten (scenario und period) im Ergebnis, das nach dem row_name und vor der Kategorie kommen muß. Sie müssen periodzweimal auflisten, um die ursprüngliche Spalte zusätzlich zu erhalten - redundant, als ob es scheinen könnte.

Basics:

zu diesem speziellen Fall Verwandte:


Normalerweise würden Sie eine Abfrage wie folgt aus:

SELECT id, scenario, p1, p2, p3, p4 -- all except aux column rn 
FROM crosstab(
    'SELECT rank() OVER (ORDER BY id, scenario)::int AS rn 
     , id, scenario, period, ct 
    FROM m 
    ORDER BY 1' 
, 'VALUES (1), (2), (3), (4)' 
    ) AS (rn int, id int, scenario int, p1 int, p2 int, p3 int, p4 int); 

Mit einer Leistung wie folgt aus:

id scenario p1 p2 p3 p4 
2 1   1 1 1 1 
2 2   1 1 1 1 
2 3   1 1 1 1 

Beachten Sie die Verwendung von rank() statt row_number() gruppieren gleichen Kombinationen von (id, scenario) zusammen .
Das Ergebnis ist sinnvoller, wenn die Zählungen nicht alle 1 sind.

+0

Hallo Erwin, Danke für die Beantwortung meiner Frage! Ich habe eine Follow-up-Frage bezüglich der Kreuztabellenfunktion. Es stellt sich heraus, dass meine Kreuztabellenfunktion Wertspalten durch Auswahl von IDs aus einer anderen Tabelle angeben soll (der zweite Parameter meiner Kreuztabellenfunktion wäre "SELECT id_prod FROM prod;"). Wie kann ich das Ende meiner Abfrage ändern (nach AS (rn int, ...)), um die Ergebnisse dieser Änderung korrekt anzuzeigen? –