web-dev-qa-db-ja.com

PostgreSQLのJson配列から要素を取得する方法

私はこれについてかなり検索しましたが、まだ答えられません。 PostgreSQLを使用しています。以下の例では、列名は「セクション」、列タイプはjson []です。

私の列はデータベースでは次のようになります:

_sections
[{"name"      : "section1",
  "attributes": [{"attrkey1": "value1",
                  "attrkey2": "value2"},

                 {"attrkey3": "value3",
                  "attrkey4": "value4"}]
 },
 {"name"      : "section2",
  "attributes": [{"attrkey3": "value5",
                  "attrkey6": "value6"},

                 {"attrkey1": "value7",
                  "attrkey8": "value8"}]
 }]
_

それはjson配列であり、結果に「attrkey3」を取得したいと考えています。 Jsonから特定のキーを取得するには、完全に正常に動作しているjson_extract_path_text(json_column, 'json_property')を使用できます。しかし、json []からプロパティを取得する方法はわかりません。

上記の例について話す場合、結果に表示されるプロパティ「attrkey2」の値を取得したいと考えています。私はそれが配列であることを知っているので、通常とは異なる動作をする可能性があります。私の配列のすべての値は別の行として機能するため、サブクエリを作成する必要があるかもしれませんが、その方法はわかりません。

また、静的にインデックスを記述して、特定のインデックスからjson要素のプロパティを取得することはできません。私のクエリは動的に生成されるので、json配列内に要素がいくつあるかわかりません。

静的な例をいくつか見ましたが、私の場合、それを実装する方法がわかりません。クエリでこれを行う方法を誰かに教えてもらえますか?

13
Mital Pritmani

_json[]_(json値のPostgreSQL配列)型付き列、またはJSON配列のように見えるjson型付き列があるかどうかはわかりません(例)。

どちらの場合も、クエリを実行する前に配列を拡張する必要があります。 _json[]_の場合、 unnest(anyarray) ;を使用する必要があります。 json型付き列のJSON配列の場合は、 json_array_elements(json) (および LATERAL 結合を使用する必要があります-それらは私の例では暗黙的です):

_select     t.id,
           each_section ->> 'name' section_name,
           each_attribute ->> 'attrkey3' attrkey3
from       t
cross join unnest(array_of_json) each_section
cross join json_array_elements(each_section -> 'attributes') each_attribute
where      (each_attribute -> 'attrkey3') is not null; 
-- use "where each_attribute ? 'attrkey3'" in case of jsonb


select     t.id,
           each_section ->> 'name' section_name,
           each_attribute ->> 'attrkey3' attrkey3
from       t
cross join json_array_elements(json_array) each_section
cross join json_array_elements(each_section -> 'attributes') each_attribute
where      (each_attribute -> 'attrkey3') is not null;
_

SQLFiddle

残念ながら、データでインデックスを使用することはできません。そのためには、まずスキーマを修正する必要があります。

22
pozs

また、arrayにキー値マップデータがあった場合:

select each_data -> 'value' as value3 
from t cross join jsonb_array_elements(t.sections -> 'attributes') each_attribute 
where each_attribute -> 'key' = '"attrkey3"'

素晴らしい答えが私の場合に完璧な解決策を提供したので、私はこれについて言及しています。ちなみに、jsonb_array .. jsonbタイプ属性のメソッド。

3
memomaster