Deze vraag was een stuk moeilijker oplossen dan je misschien had verwacht. Uw poging met crosstab()
in de goede richting mikte. Maar om dynamische kolomnamen toe te wijzen heb je daarnaast dynamische SQL nodig:EXECUTE
in een plpgsql-functie.
Wijzig het gegevenstype van de kolom infos.type
van text
naar regtype
om SQL-injectie en andere fouten te voorkomen. U hebt bijvoorbeeld het gegevenstype number
, wat geen geldig PostgreSQL-gegevenstype is. Ik heb het vervangen door numeric
, zodat het kan werken.
Je zou vereenvoudig de taak door kolomnamen te vermijden die dubbele aanhalingstekens nodig hebben. Zoals nume_anterior
in plaats van "nume anterior"
.
Misschien wilt u een kolom row_id
. toevoegen naar uw tabel info_data
om alle elementen van één rij te markeren. Je hebt het nodig voor de crosstab()
functie, en u kunt kolommen negeren met NULL
waarden. De crosstab()
functie met twee parameters kan omgaan met ontbrekende kolommen. Ik synthetiseer de ontbrekende kolom met de uitdrukking (d.id-1)/13
hieronder - wat werkt voor de gegevens in uw voorbeeld.
U moet de aanvullende module tablefunc installeren (eenmaal per database):
CREATE EXTENSION tablefunc;
Zoek aanvullende uitleg en links in dit gerelateerde antwoord .
Deze functie doet wat je zoekt:
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$;
Bel:
SELECT * FROM x.mytbl();
Raak niet in de war door de geneste dollarcitaten .
BTW:ik heb de kolomlijst gemaakt met deze verklaring:
SELECT 'id int,' || string_agg(quote_ident(name) || ' ' || type
,', ' ORDER BY i.id)
FROM infos i;