存储在jsonb中的Postgres数组总和

时间:2019-03-16 19:21:54

标签: arrays json postgresql aggregate-functions jsonb

我有一个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 个答案:

答案 0 :(得分:1)

在横向连接中使用该功能:

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中的每一行执行一次。