この質問はもっと大変でした あなたが予想したよりも解決するために。 crosstab()での試み 正しい方向を目指していました。ただし、動的列名を割り当てるには、さらに動的SQLが必要です。 EXECUTE plpgsql関数で。
列infos.typeのデータ型を変更します textから regtype
SQLインジェクションやその他のエラーを防ぐため。たとえば、データ型がnumberであるとします。 、これは有効なPostgreSQLデータ型ではありません。 numericに置き換えました
、それで動作します。
あなたはできた 二重引用符を必要とする列名を回避することにより、タスクを単純化します。 nume_anteriorのように "nume anterior"の代わりに 。
列row_idを追加することをお勧めします テーブルにinfo_data 1行のすべての要素をマークします。 crosstab()に必要です 関数であり、NULLの列を無視できます 値。 crosstab() 2つのパラメーターを持つ関数は、欠落している列を処理できます。欠落している列を(d.id-1)/13という式で合成します 以下-これはあなたの例のデータに対して機能します。
追加モジュールtablefunc をインストールする必要があります (データベースごとに1回):
CREATE EXTENSION tablefunc;
この関数は、探しているものを実行します:
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$;
電話:
SELECT * FROM x.mytbl();
ネストされた
ところで:私はこのステートメントで列リストを作成しました:
SELECT 'id int,' || string_agg(quote_ident(name) || ' ' || type
,', ' ORDER BY i.id)
FROM infos i;