Использовать объединение в json установить функцию возврата - PullRequest
0 голосов
/ 12 февраля 2020

У меня есть данные, которые хранятся немного странным образом, но я должен над этим поработать. Следующий образец представляет его структуру:

https://www.db-fiddle.com/f/rAALhAatyedGgXK5LxvLeG/3

create table tickets
(ticket_id integer,
 properties text);

 insert into tickets
 values
 (123,'[{"details":[
{"amount":"5","price":150},
{"amount":"2","price":200}]}]'),

(124,'[{"details":[
{"price":430}
]}]'),

(125,'[{"details":[] }]');

Мне удалось извлечь необходимые данные, вероятно, не самым элегантным способом, но вывод составляет ПОЧТИ что мне нужно.

SELECT 
ticket_id,
REPLACE((json_array_elements(json_array_elements(properties::json)->'details')->'amount')::TEXT, '"','')::int as amount,
((json_array_elements(json_array_elements(properties::json)->'details')->'price')::text)::int AS price
FROM tickets

ticket_id   amount  price
123         5       150
123         2       200
124         null    430

Пропущенная запись - ticket 125 с null в столбцах amount и price. Почему он уходит от результатов, если отсутствуют как цена, так и сумма, но дает нулевое значение, если отсутствует только один из них?

@ edit Я нашел причину, если данные массива пусты, они не содержат json больше не надо. Но все равно думаю, как это преодолеть.

В идеале я хотел бы использовать coalesce и поставить туда 1, если он нулевой, но дает

ERROR:  set-returning functions are not allowed in COALESCE

Как я могу обойти это?

1 Ответ

2 голосов
/ 12 февраля 2020

Набор возвращаемых функций должен использоваться в предложении FROM.

Чтобы включить строку с id = 125 (с пустым массивом), вам нужно использовать внешнее объединение с функцией jsonb_array_elements(), чтобы включить строки с пустым результатом.

SELECT ticket_id, 
       (d.detail ->> 'price')::int as price,
       (d.detail ->> 'amount')::int as amount
FROM tickets
  left join jsonb_array_elements( ((properties::Jsonb) -> 0) -> 'details' ) as d(detail) on true

Онлайн пример

...