タイプjsonb
のフィールドを持つテーブルがあります。すべてのjsonキーに対してフィールドjsonbの列を分割したいと思います。この列にはスキーマがありません。例えば:
から
CREATE TABLE v(id,jsonb)
AS VALUES
(1,'{"a":"4", "b":"5"}'::jsonb),
(2,'{}'),
(3,'{"a":"8", "c":"9", "d":"9"}');
に
id | a | b | c | d
1 | 4 | 5 | |
3 | 8 | | 9 | 9
この特定のケースでは、1つの解決策は
select * from table, json_to_record(optional) as x("a" text, "b" text, "c" text, d text)
ご覧のとおり、キーは変化する可能性があり、大きなデータベースではすべてのキーを実際の問題に配置することが困難です。31個のキーがありますが、他のテーブルでこのスクリプトを再利用したい場合は、手動でキーを入力する必要があります。
キーを手動で指定せずにjsonbのキー全体を選択する方法はありますか?
私の質問:キーを手動で指定せずにjsonbのキー全体を選択する方法はありますか?
いいえ、クエリが未定義の結果セットを返す方法はありません。ただし、テーブルが新しいクエリを受け入れない場合は、動的SQLステートメントを生成できます。
SELECT FORMAT(
$$ SELECT * FROM %I.%I CROSS JOIN LATERAL jsonb_to_record(%I) AS rs(%s); $$,
'public',
'v',
'jsonb',
array_to_string(
(SELECT ARRAY(SELECT DISTINCT col FROM v CROSS JOIN LATERAL jsonb_object_keys(jsonb) AS t(col) ORDER BY col)), ' text , '
) || ' text'
);
次に、そのクエリを実行するか、psqlで\gexec
を実行します。
format
--------------------------------------------------------------------------------------------------------------
SELECT * FROM public.v CROSS JOIN LATERAL jsonb_to_record(jsonb) AS rs(a text , b text , c text , d text);
(1 row)
test=# \gexec
id | jsonb | a | b | c | d
----+--------------------------------+---+---+---+---
1 | {"a": "4", "b": "5"} | 4 | 5 | |
2 | {} | | | |
3 | {"a": "8", "c": "9", "d": "9"} | 8 | | 9 | 9
(3 rows)
jsonb_typeof
を使用して型推論を構築してpg型に戻したい場合も、そうでない場合もあります。整数などに戻ることはできませんが、double precision
として数値を格納できるはずです。