PostgreSQL按行聚合JSON记录集键

3

我有一些存储在PostgreSQL表中的JSON数组,每个数组对应一个表行,格式如下:

id          data
-------------------------------------------------
1           [{"a": 1, "b": 2}, {"a": 3, "b":2}]
2           [{"a": 5, "b": 8}, {"a": 9, "b":0}]

如何按id分组并获取记录集中特定键的总和?以下是所需结果集的示例:

id          a           b
-------------------------------------------------
1           4           4
2           14          8

更新:

我还应该提到,数据列是jsonb数据类型。

2个回答

4
select id, sum(a), sum(b)
  from jsontable j
    CROSS JOIN LATERAL
    json_to_recordset(j.data) as x(a integer, b integer)
group by id

您可以在此处测试查询或对其进行微调 http://rextester.com/ZTCY82930

有关json_to_recordset的文档,请参见https://www.postgresql.org/docs/9.6/static/functions-json.html

关于交叉连接,请参见https://www.reddit.com/r/PostgreSQL/comments/2u6ah3/how_to_use_json_to_recordset_on_json_stored_in_a/co6hr65/

编辑:正如您在更新中所述,您使用了一个jsonb字段,因此不需要使用json_to_recordset,只需使用jsonb_to_recordset


1
这是我第一次使用Postgres的新JSON函数,它们非常棒!我有一个使用名为test的表的解决方案。
我将数组元素拆分,然后将其扩展为键值对,然后在外部查询中对它们进行求和。
我不得不做一个令人讨厌的双重转换::text::integer,以将JSON值作为整数获取,因为我发现你不能直接从JSON转换为整数,就像我在this answer中发现的那样。
我发现了如何分解键值元组在这个教程中
SELECT id,
    SUM(CASE WHEN k = 'a' THEN v ELSE 0 END) AS a,
    SUM(CASE WHEN k = 'b' THEN v ELSE 0 END) AS b
FROM (
    SELECT id, 
        (json_each(json_array_elements(data))).key as k, 
        (json_each(json_array_elements(data))).value::text::integer AS v FROM test
) AS json_data
GROUP BY id

给出结果:
id | a  | b
-----------
1  | 4  | 4
2  | 14 | 8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接