Diese Frage war viel schwieriger zu lösen, als Sie vielleicht erwartet haben. Ihr Versuch mit crosstab()
zielte in die richtige Richtung. Aber um dynamische Spaltennamen zu vergeben, benötigen Sie zusätzlich dynamisches SQL:EXECUTE
in einer plpgsql-Funktion.
Ändern Sie den Datentyp der Spalte infos.type
aus text
zu regtype
um SQL-Injection und andere Fehler zu verhindern. Sie haben zum Beispiel den Datentyp number
, was kein gültiger PostgreSQL-Datentyp ist. Ich habe es durch numeric
ersetzt
, damit es funktionieren kann.
Sie könnten Vereinfachen Sie die Aufgabe, indem Sie Spaltennamen vermeiden, die doppelte Anführungszeichen erfordern. Wie nume_anterior
statt "nume anterior"
.
Vielleicht möchten Sie eine Spalte row_id
hinzufügen zu Ihrer Tabelle info_data
um alle Elemente einer Zeile zu markieren. Sie benötigen es für die crosstab()
-Funktion und erlaubt Ihnen, Spalten mit NULL
zu ignorieren Werte. Die crosstab()
Funktion mit zwei Parametern kann mit fehlenden Spalten umgehen. Ich synthetisiere die fehlende Spalte mit dem Ausdruck (d.id-1)/13
unten - was für die Daten in Ihrem Beispiel funktioniert.
Sie müssen das Zusatzmodul tablefunc installieren (einmal pro Datenbank):
CREATE EXTENSION tablefunc;
zusätzliche Erläuterungen und Links in dieser zugehörigen Antwort .
Diese Funktion wird das tun, wonach gesucht wird:
CREATE OR REPLACE FUNCTION f_mytbl()
RETURNS TABLE (id int
, nume text , prenume text , cnp numeric
, "nume anterior" text, "stare civila" text, cetatenie text
, rezidenta text , adresa text , "tip act" text
, "serie ci" text , "numar ci" text , "data eliberarii" text
, "eliberat de" text)
LANGUAGE plpgsql AS
$BODY$
BEGIN
RETURN QUERY EXECUTE $f$
SELECT *
FROM crosstab(
'SELECT (d.id-1)/13 -- AS row_id
, i.id, d.value
FROM infos i
JOIN info_data d ON d.id_info = i.id
ORDER BY 1, i.id',
'SELECT id
FROM infos
ORDER BY id'
)
AS tbl ($f$ || 'id int,
, nume text , prenume text , cnp numeric
, "nume anterior" text, "stare civila" text, cetatenie text
, rezidenta text , adresa text , "tip act" text
, "serie ci" text , "numar ci" text , "data eliberarii" text
, "eliberat de" text)';
END;
$BODY$;
Aufruf:
SELECT * FROM x.mytbl();
Lassen Sie sich nicht durch die verschachtelten Dollar-Notierung .
Übrigens:Ich habe die Spaltenliste mit dieser Anweisung erstellt:
SELECT 'id int,' || string_agg(quote_ident(name) || ' ' || type
,', ' ORDER BY i.id)
FROM infos i;