Postgres сумма массива, сохраненного в jsonb - PullRequest
1 голос
/ 16 марта 2019

У меня есть база данных postgres, где некоторые данные хранятся в виде массивов jsonb:

 id |         start          |   duration   |   value    
----+------------------------+--------------+------------
  1 | 2019-01-04 18:34:00+01 | [60]         | [7]
  2 | 2019-01-04 18:44:00+01 | [60]         | [9]
  3 | 2019-01-04 19:00:00+01 | [60]         | [6]
  4 | 2019-01-04 19:06:00+01 | [60]         | [17]
  5 | 2019-01-04 19:19:00+01 | [60]         | [9]
  6 | 2019-01-04 19:41:00+01 | [60, 60, 60] | [13, 8, 9]
  7 | 2019-01-04 19:46:00+01 | [60]         | [7]
  8 | 2019-01-04 19:49:00+01 | [60]         | [0]

Я хотел бы получить сумму всех значений в массиве в поле «значение».

Я могу получить все значения из массивов, используя jsonb_array_elements:

=# select jsonb_array_elements(value),value from step limit 20;
 jsonb_array_elements |   value    
----------------------+------------
 7                    | [7]
 9                    | [9]
 6                    | [6]
 17                   | [17]
 9                    | [9]
 13                   | [13, 8, 9]
 8                    | [13, 8, 9]
 9                    | [13, 8, 9]
 7                    | [7]

и так далее. Вот я и подумал

select sum(jsonb_array_elements(value)::integer),start from step group by start

сделал бы это, но мне сказали: ОШИБКА: вызовы агрегатных функций не могут содержать вызовы функций, возвращающие множество СОВЕТ: Возможно, вы сможете переместить функцию возврата набора в элемент LATERAL FROM.

Я немного заглянул в LATERAL FROM, но до сих пор не понимаю, чего хочет от меня postgres ...

Было бы проще сделать это, если бы я сохранял длительность и значение как массивы, а не как json?

1 Ответ

1 голос
/ 16 марта 2019

Используйте функцию в боковом соединении:

select start, sum(number::int)
from step s
cross join jsonb_array_elements_text(value) as number
group by start

         start          | sum 
------------------------+-----
 2019-01-04 19:00:00+01 |   6
 2019-01-04 19:46:00+01 |   7
 2019-01-04 18:44:00+01 |   9
 2019-01-04 19:19:00+01 |   9
 2019-01-04 18:34:00+01 |   7
 2019-01-04 19:06:00+01 |  17
 2019-01-04 19:49:00+01 |   0
 2019-01-04 19:41:00+01 |  30
(8 rows)

Это перекрестное соединение является боковым соединением, функция выполняется один раз для каждой строки из step.

...