Как объединить два значения JSON-массива в определенном порядке? - PullRequest
1 голос
/ 04 июня 2019

Я использую PostgreSQL 9.5. У меня есть таблица с массивами JSON, которые содержат JSON-объекты в следующем формате:

[]
[{animal:cat}, {plant:sunflower}, {car:mercedes}]
[{animal:dog}]
[{animal:dog}, {car:audi}]
[]

Мне нужно вывести таблицу, которая объединяет значения animal и plant , а затем вычисляет сумму каждой комбинации значений ключа. Нулевые значения следует игнорировать, но ситуации, в которых есть только animal или plant , также группируются как их собственная группа. автомобиль должен быть полностью удален.

Мой идеальный конечный результат похож на это:

Animal : Plant     |  Amount
---------------------------
cat : oak          |   54
cat : sunflower    |   127
dog                |   8
cow : oak          |   3
...

Что я пытался:

SELECT
    ((json_array_elements(Table.json_array)::JSONB
- 'car')::JSON#>>'{animal}')::TEXT AS elems,
    count(*)
FROM    Table
GROUP BY elems

Я вижу, что это дает мне animal в виде строки и считает каждый ее экземпляр. Я также могу удалить car , приведя массив JSON к JSONB, затем удалить car с оператором минус и вернуть обратно в JSON. Однако приведение к JSONB меняет порядок моих значений.

Но когда я пытаюсь объединить строку из animal и plant :

SELECT
    (((json_array_elements(Table.json_array))::JSON#>>'{animal}') || ' : ' || ((json_array_elements(Table.json_array))::JSON#>>'{plant}'))
    ::TEXT AS elems,
    count(*)
FROM    Table
GROUP BY elems

Я получаю сообщение об ошибке:

функции и операторы могут принимать не более одного установленного аргумента

Пробовал json_agg, CONCAT() и ||, тот же результат.

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

Как получить желаемый результат? Я ограничен использованием только команд Postgres, так как я работаю с базой данных через Apache superset, программу визуализации данных.

1 Ответ

3 голосов
/ 04 июня 2019

В одну сторону:

SELECT animal_plant, count(*)
FROM  (
   SELECT t.id, concat_ws(' : '
                        , string_agg(elem ->> 'animal', '|')
                        , string_agg(elem ->> 'plant' , '|')) AS animal_plant
   FROM   tbl t, json_array_elements(t.json_array) j(elem)
   GROUP  BY t.id
   ) sub
GROUP  BY 1
ORDER  BY 1;

Это объединяет всех кошек и всех собак с одинаковым значением JSON, так как вы не раскрыли, может ли быть несколько.(Если существует не более одного каждого, он дает желаемый результат.)

db <> fiddle здесь

Может быть проще с SQL/ JSON в Postgres 12 ...
(В любом случае, вам потребуется в ближайшее время перейти на современную версию Postgres.)

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