Pertanyaan ini jauh lebih sulit untuk memecahkan dari yang mungkin Anda harapkan. Upaya Anda dengan crosstab()
sedang membidik ke arah yang benar. Tetapi untuk menetapkan nama kolom dinamis, Anda memerlukan SQL dinamis sebagai tambahan:EXECUTE
dalam fungsi plpgsql.
Ubah tipe data kolom infos.type
dari text
ke regtype
untuk mencegah injeksi SQL dan kesalahan lainnya. Misalnya, Anda memiliki tipe data number
, yang bukan tipe data PostgreSQL yang valid. Saya menggantinya dengan numeric
, sehingga dapat bekerja.
Anda bisa sederhanakan tugas dengan menghindari nama kolom yang memerlukan tanda kutip ganda. Seperti nume_anterior
bukannya "nume anterior"
.
Anda mungkin ingin menambahkan kolom row_id
ke tabel Anda info_data
untuk menandai semua elemen dari satu baris. Anda membutuhkannya untuk crosstab()
fungsi, dan memungkinkan Anda untuk mengabaikan kolom dengan NULL
nilai-nilai. crosstab()
fungsi dengan dua parameter dapat menangani kolom yang hilang. Saya mensintesis kolom yang hilang dengan ekspresi (d.id-1)/13
di bawah ini - yang berfungsi untuk data dalam contoh Anda.
Anda perlu menginstal tablefunc modul tambahan (sekali per basis data):
CREATE EXTENSION tablefunc;
Temukan penjelasan dan tautan tambahan dalam jawaban terkait ini .
Fungsi ini akan melakukan apa yang dicari:
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$;
Telepon:
SELECT * FROM x.mytbl();
Jangan bingung dengan penawaran dolar .
BTW:Saya membuat daftar kolom dengan pernyataan ini:
SELECT 'id int,' || string_agg(quote_ident(name) || ' ' || type
,', ' ORDER BY i.id)
FROM infos i;