To pytanie było o wiele trudniejsze rozwiązać, niż mogłeś się spodziewać. Twoja próba z crosstab()
zmierzał we właściwym kierunku. Ale aby przypisać dynamiczne nazwy kolumn, potrzebujesz dodatkowo dynamicznego SQL:EXECUTE
w funkcji plpgsql.
Zmień typ danych kolumny infos.type
z text
do regtype
aby zapobiec wstrzyknięciu SQL i innym błędom. Na przykład masz typ danych number
, który nie jest prawidłowym typem danych PostgreSQL. Zamieniłem go na numeric
, więc może działać.
możesz uprość zadanie, unikając nazw kolumn, które wymagają podwójnego cudzysłowu. Jak nume_anterior
zamiast "nume anterior"
.
Możesz dodać kolumnę row_id
do Twojej tabeli info_data
aby zaznaczyć wszystkie elementy jednego rzędu. Potrzebujesz go do crosstab()
funkcja i pozwala ignorować kolumny z NULL
wartości. crosstab()
funkcja z dwoma parametrami może poradzić sobie z brakującymi kolumnami. Brakującą kolumnę syntetyzuję za pomocą wyrażenia (d.id-1)/13
poniżej - co działa dla danych w twoim przykładzie.
Musisz zainstalować dodatkowy moduł tablefunc (raz na bazę danych):
CREATE EXTENSION tablefunc;
Znajdź dodatkowe wyjaśnienia i linki w tej powiązanej odpowiedzi .
Ta funkcja zrobi to, czego szukasz:
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$;
Zadzwoń:
SELECT * FROM x.mytbl();
Nie daj się zmylić zagnieżdżonym cytowanie dolara .
BTW:Stworzyłem listę kolumn za pomocą tego stwierdzenia:
SELECT 'id int,' || string_agg(quote_ident(name) || ' ' || type
,', ' ORDER BY i.id)
FROM infos i;