まず、JSONは複数のテーブルのデータを結合するときの通常のフィールドと変わりません。物事は非常に迅速に複雑になる可能性があります。管理しやすいものを維持するためにいくつかのテクニックは、しかし、があります。
1.デイジーチェーン機能
は、それぞれ独立して機能からの出力を処理する必要はありません、あなたはように、1つの関数からの出力を供給することができます1つのステートメントで次への入力。あなたの例では、これは集計レベルごとにレベルの下位選択を失うことを意味し、エイリアスを忘れる可能性があります。あなたの例では、次のようになります。
select row_to_json(row(image_type.name, (
select json_agg(image_instance.name, (
select json_agg(image_version.name)
from image_version
where image_version.image_instance_id = image_instance.id) -- join edited
from image_instance
where image_instance.image_type_id = image_type.image_type_id))))
from image_type;
2.これは個人的な好みの問題かもしれないが、スカラサブクエリを読み込み(と書き込みするのは困難になる傾向があり、スカラサブクエリし
を使用しないでください:私のポイントを説明するために、最も内側のスカラーサブクエリの結合条件に明らかなエラーがありました。
select row_to_json(row(it.name, iiv.name))
from image_type it
join (select image_type_id, json_agg(name, iv_name) as name
from image_instance ii
join (select image_instance_id, json_agg(name) as iv_name
from image_version group by 1) iv on iv.image_instance_id = ii.id
group by 1) iiv using (image_type_id);
3.モジュール化the beginning of the documentation, in the Tutorial sectionで右そこ
(強く推奨読み、あなたがいると思うが堪能):
明示的ではなく、結合と集計との定期的なサブクエリを使用します
ビューのリベラルな使用は、良いSQLデータベース デザインの重要な側面です。
create view iv_json as
select image_instance_id, json_agg(name) as iv_name
from image_version
group by 1;
create view ii_json as
select image_type_id, json_agg(name, iv_name) as name
from image_instance
join iv_json on image_instance_id = image_instance.id
group by 1;
あなたのメイン・クエリは現在次のようになります。
select row_to_json(row(it.name, ii.name))
from image_type it
join ii_json ii using (image_type_id);
のように...
これは、はるかに明らかに、テストをコーディングし、維持するのが最も簡単です。パフォーマンスはここでは問題になりません。クエリオプティマイザは、リンクされたすべてのビューを単一の実行計画にフラット化します。
最後の注意:あなたはPG9.4の+を使用している場合は、よりわかりやすい出力用json_build_object()
の代わりrow_to_json()
を使用することができます。
@a_horse_with_no_nameこれを拡張できますか?あなたが参照した記事を読んだが、私のデータはJSONブロブではなく正規化されたテーブルに保存されている。私はこれらのテーブルからJSON本体を生成したいだけです。おそらくあなたがもう少し拡大することができれば、それは私の理解を助けるでしょう。 –