Questa domanda era molto più difficile da risolvere di quanto potresti aspettarti. Il tuo tentativo con crosstab()
mirava nella giusta direzione. Ma per assegnare nomi di colonna dinamici è necessario anche SQL dinamico:EXECUTE
in una funzione plpgsql.
Modifica il tipo di dati della colonna infos.type
da text
a regtype
per prevenire SQL injection e altri errori. Ad esempio, hai il tipo di dati number
, che non è un tipo di dati PostgreSQL valido. L'ho sostituito con numeric
, quindi può funzionare.
Potresti semplificare l'attività evitando i nomi di colonna che necessitano di virgolette doppie. Come nume_anterior
invece di "nume anterior"
.
Potresti voler aggiungere una colonna row_id
alla tua tabella info_data
per contrassegnare tutti gli elementi di una riga. Ne hai bisogno per il crosstab()
e ti permette di ignorare le colonne con NULL
i valori. La crosstab()
la funzione con due parametri può gestire le colonne mancanti. Sintetizzo la colonna mancante con l'espressione (d.id-1)/13
sotto - che funziona per i dati nel tuo esempio.
È necessario installare il modulo aggiuntivo tablefunc (una volta per database):
CREATE EXTENSION tablefunc;
Trova ulteriori spiegazioni e link in questa risposta correlata .
Questa funzione farà ciò che stai cercando:
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$;
Chiama:
SELECT * FROM x.mytbl();
Non lasciarti confondere dal citazione del dollaro .
A proposito:ho creato l'elenco delle colonne con questa affermazione:
SELECT 'id int,' || string_agg(quote_ident(name) || ' ' || type
,', ' ORDER BY i.id)
FROM infos i;