Запрос таблицы базы данных JSON

#sql #arrays #json #postgresql #lateral-join

#sql #массивы #json #postgresql #боковое соединение

Вопрос:

У меня есть таблица JSON с некоторыми объектами, и я пытаюсь запросить значение суммы в объекте

 {
"authorizations": [
{
  "id": "d50",
  "type": "passed",
  "amount": 100,
  "fortId": 5050,
  "status": "GENERATED",
  "voided": false,
  "cardNumber": 3973,
  "expireDate": null,
  "description": "Success",
  "customerCode": "858585",
  "paymentMethod": "cash",
  "changeDatetime": null,
  "createDatetime": 000000000,
  "reservationCode": "202020DD",
  "authorizationCode": "D8787"
},
{
  "id": "d50",
  "type": "passed",
  "amount": 100,
  "fortId": 5050,
  "status": "GENERATED",
  "voided": false,
  "cardNumber": 3973,
  "expireDate": null,
  "description": "Success",
  "customerCode": "858585",
  "paymentMethod": "cash",
  "changeDatetime": null,
  "createDatetime": 000000000,
  "reservationCode": "202020DD",
  "authorizationCode": "D8787"
 }
 ],
 }
 

Я попробовал следующие четыре варианта, но ни один из них не дает мне значение объекта:

 SELECT info @> 'authorizations:[{amount}]'
FROM idv.reservations;

SELECT info -> 'authorizations:[{amount}]'
FROM idv.reservations;

info -> ''authorizations' ->> 'amount'
FROM idv.reservations

select (json_array_elements(info->'authorizations')->'amount')::int from idv.reservations
 

обратите внимание, что я использую DBeaver

Ответ №1:

Если вам нужна одна строка для каждого объекта, содержащегося в массиве JSON «авторизации», с соответствующим количеством, вы можете использовать боковое соединение и jsonb_array_elements() :

 select r.*, (x.obj ->> 'amount')::int as amount
from reservations r
cross join lateral jsonb_array_elements(r.info -> 'authorizations') x(obj)
 

Мы также можем извлечь все суммы сразу и поместить их в массив, например:

 select r.*, 
    jsonb_path_query_array(r.info, '$.authorizations[*].amount') as amounts
from reservations r
 

Демонстрация на DB Fiddlde