この質問はもっと大変でした あなたが予想したよりも解決するために。 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;