【问题标题】:PostgreSQL - Aggregate values in JSON object without specifying keysPostgreSQL - 在 JSON 对象中聚合值而不指定键
【发布时间】:2021-04-28 19:19:46
【问题描述】:

我正在尝试获取由shop_id 和键分组的 JSON 数组中的值的总和,并以相同的格式获取输出。

所以,使用这样的数组:

[
    {
        sales: {"bicycle": 2, "skateboard": 5},
        shop_id: 6321
    },
    {
        sales: {"bicycle": 1, "skateboard": 3},
        shop_id: 6243
    },
    {
        sales: {"bicycle": 3, "skateboard": 4},
        shop_id: 6243
    }
]

输出应如下所示:

[
    {
        sales: {"bicycle": 2, "skateboard": 5},
        shop_id: 6321
    },
    {
        sales: {"bicycle": 4, "skateboard": 7},
        shop_id: 6243
    }
]

JSON 输入将始终是统一的。如果我使用JSON_BUILD_OBJECTJSON_AGG,我可以让它工作,但我不想指定在构建 JSON 时使用什么键,因为真实数据可能包含大约 20 个不同的键,所以我正在寻找一个更清洁的解决方案。

SELECT JSON_BUILD_OBJECT('bicycle', SUM((sales::json ->> 'bicycle')::int),
                         'skateboard', SUM((sales::json ->> 'skateboard')::int)
           ) AS sales,
       shop_id
FROM (SELECT val ->> 'sales' AS sales, val ->> 'shop_id' AS shop_id
      FROM (SELECT UNNEST($1)::jsonb AS val) core) outercore
GROUP BY shop_id;

我怎样才能实现这样的目标?

【问题讨论】:

  • 您使用的是哪个 Postgres 版本?
  • 11.9 但有计划稍后升级到 13.2

标签: json postgresql


【解决方案1】:

您需要将所有项目提取为键/值对,然后您可以将它们聚合回单个 JSON:

select jsonb_agg(s)
from (
  select shop_id, 
         jsonb_object_agg(typ, value) as sales
  from (       
    select (t.item ->> 'shop_id')::int as shop_id,
           s.typ, 
           sum(value::int) as value
    from your_table yt --<< this is where the json column comes from
      cross join jsonb_array_elements(yt.val) as t(item)
      cross join jsonb_each(t.item -> 'sales') as s(typ, value)
    group by id, shop_id, typ 
  ) x
  group by id, shop_id  
) s  
;

Online example

【讨论】:

    猜你喜欢
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 2013-06-06
    • 2021-09-02
    • 2020-12-26
    相关资源
    最近更新 更多