Den här frågan var mycket svårare att lösa än du kanske har förväntat dig. Ditt försök med crosstab()
siktade åt rätt håll. Men för att tilldela dynamiska kolumnnamn behöver du dessutom dynamisk SQL:EXECUTE
i en plpgsql-funktion.
Ändra datatypen för kolumnen infos.type
från text
till regtype
för att förhindra SQL-injektion och andra fel. Du har till exempel datatypen number
, som inte är en giltig PostgreSQL-datatyp. Jag ersatte den med numeric
, så det kan fungera.
Du kunde förenkla uppgiften genom att undvika kolumnnamn som behöver dubbla citat. Som nume_anterior
istället för "nume anterior"
.
Du kanske vill lägga till en kolumn row_id
till din tabell info_data
för att markera alla element i en rad. Du behöver den för crosstab()
funktion, och den låter dig ignorera kolumner med NULL
värden. crosstab()
funktion med två parametrar kan hantera saknade kolumner. Jag syntetiserar den saknade kolumnen med uttrycket (d.id-1)/13
nedan - vilket fungerar för data i ditt exempel.
Du måste installera ytterligare modul tablefunc (en gång per databas):
CREATE EXTENSION tablefunc;
Hitta ytterligare förklaring och länkar i det här relaterade svaret .
Denna funktion kommer att göra vad du letar efter:
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$;
Ring:
SELECT * FROM x.mytbl();
Bli inte förvirrad av den kapslade notering i dollar .
BTW:Jag skapade kolumnlistan med detta uttalande:
SELECT 'id int,' || string_agg(quote_ident(name) || ' ' || type
,', ' ORDER BY i.id)
FROM infos i;