Tato otázka byla mnohem těžší vyřešit, než jste možná čekali. Váš pokus s crosstab()
mířil správným směrem. Ale k přiřazení dynamických názvů sloupců potřebujete navíc dynamické SQL:EXECUTE
ve funkci plpgsql.
Změňte datový typ sloupce infos.type
z text
na regtype
aby se zabránilo vkládání SQL a dalším chybám. Máte například datový typ number
, což není platný datový typ PostgreSQL. Nahradil jsem jej numeric
, takže to může fungovat.
Mohli byste zjednodušte úlohu tím, že se vyhnete názvům sloupců, které vyžadují dvojité uvozovky. Jako nume_anterior
místo "nume anterior"
.
Možná budete chtít přidat sloupec row_id
do vaší tabulky info_data
pro označení všech prvků jednoho řádku. Potřebujete jej pro crosstab()
a umožňuje vám ignorovat sloupce s NULL
hodnoty. crosstab()
funkce se dvěma parametry si dokáže poradit s chybějícími sloupci. Chybějící sloupec syntetizuji výrazem (d.id-1)/13
níže – což funguje pro data ve vašem příkladu.
Je třeba nainstalovat přídavný modul tablefunc (jednou pro databázi):
CREATE EXTENSION tablefunc;
Najděte další vysvětlení a odkazy v této související odpovědi .
Tato funkce udělá to, co hledáte:
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$;
Volejte:
SELECT * FROM x.mytbl();
Nenechte se zmást vnořeným dolarové kotace .
BTW:Vytvořil jsem seznam sloupců s tímto prohlášením:
SELECT 'id int,' || string_agg(quote_ident(name) || ' ' || type
,', ' ORDER BY i.id)
FROM infos i;