JSON переформатирование в PostgreSQL - PullRequest
0 голосов
/ 25 мая 2020

В таблице PostgreSQL у меня есть столбец с JSON, например:

{"elements":[{"val":"value1", "column":"column1"}, {"val":"val2", "column":"column2"}, ...]}.

Есть ли способ преобразовать это в набор результатов, например:

column1 | column2 | ...
-----------------------
value1  | value2  | ...

Я работал с PostgreSQL JSON функциями, но не нашел ответа.

Ответы [ 4 ]

2 голосов
/ 25 мая 2020

Количество столбцов запроса должно быть известно до его выполнения, поэтому вам нужно будет написать одно выражение для каждого возможного столбца в вашем массиве.

С Postgres 12, вы можете сделать это с помощью выражения JSON / Path:

select jsonb_path_query_first(input -> 'elements', '$[*].val ? ($.column == "column1")' ) #>> '{}' as column_1,
       jsonb_path_query_first(input -> 'elements', '$[*].val ? ($.column == "column2")' ) #>> '{}' as column_2
from data;

Вам нужно повторить часть jsonb_path_query_first() для каждого возможного столбца в массиве.

#>> {} используется для преобразования значения JSONB, возвращаемого функцией, в значение text.

0 голосов
/ 28 мая 2020

На основе предложения @a_horse_with_no_name:

select 
    jsonb_path_query_first(raw_data_1thbase.data -> 'elements', '$[*] ? (@.column == "column1").val' ) #>> '{}' as column1,
    jsonb_path_query_first(raw_data_1thbase.data -> 'elements', '$[*] ? (@.column == "column2").val' ) #>> '{}' as column2
from data;

сработало для меня.

0 голосов
/ 25 мая 2020

В этом примере JSON значение динамически не преобразовывается в столбцы col и val за счет использования функций json_array_elements_text() и json_each() в этом запросе

   SELECT json_array_elements_text(v)::json->>'column' AS col,
          json_array_elements_text(v)::json->>'val' AS val
     FROM tab t
    CROSS JOIN json_each(jsval) as js(k,v)

, но сводит результаты, полученные из В приведенном выше запросе столбцы должны быть указаны индивидуально, в зависимости от количества столбцов для результирующего запроса, таким образом, чтобы использовать условное агрегирование:

SELECT MAX(val) FILTER (WHERE col = 'column1') as column1,
       MAX(val) FILTER (WHERE col = 'column2') as column2,
       MAX(val) FILTER (WHERE col = 'column3') as column3
  FROM 
  (
   SELECT json_array_elements_text(v)::json->>'column' AS col,
          json_array_elements_text(v)::json->>'val' AS val
     FROM tab t
    CROSS JOIN json_each(jsval) as js(k,v)
  ) q

Демо

0 голосов
/ 25 мая 2020

Вы можете использовать функцию json_to_recordset для преобразования JSON в набор строк. В любом случае, окончательный набор строк не может иметь динамическое c количество столбцов, т.е. какое бы решение вы ни выбрали, вам придется каким-то образом перечислить их явно.

Например, в предложении select при выполнении ручной транспозиции 1: 1 -converted JSON:

with t(d) as (values 
  ('{"elements":[{"val":"value1", "column":"column1"}, {"val":"val2", "column":"column2"}]}'::json)
), matrix(val,col) as (
  select x.val, x."column"
  from t
  inner join lateral json_to_recordset((t.d->>'elements')::json) as x(val text, "column" text) on true
)
select (select val from matrix where col = 'column1') as column1
     , (select val from matrix where col = 'column2') as column2

Или в предложении as x(column1 text, column2 text) при использовании расширения crosstab (см. этот вопрос ).

Или как-то преобразовано или преобразованный в xml JSON.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...