如何使用其他列类型在 postgres 中聚合 Jsonb 列

How can I aggregate Jsonb columns in postgres using another column type

我在 postgres 中有以下数据 table,

其中数据是一个 jsonb 列。我想得到结果

[
 {field_type: "Design", briefings_count: 1, meetings_count: 13}, 
 {field_type: "Engineering", briefings_count: 1, meetings_count: 13}, 
 {field_type: "Data Science", briefings_count: 0, meetings_count: 3}
]

您可以像这样聚合列,然后将数据插入另一个 table

select array_agg(data)
from the_table

或使用内置 json 函数之一创建新的 json 数组。例如jsonb_agg(expression)

解释

使用 jsonb_each_text 函数从名为 datajsonb 列中提取数据。然后使用 GROUP BY 聚合行,为每个不同的 field_type 获取一行。对于每个聚合,我们还需要包括会议和简报计数,这是通过使用案例语句选择最大值来完成的,以便您可以为不同的计数创建两个单独的列。最重要的是,如果缺少某些信息,请将 coalesce 函数应用于 return 0 而不是 NULL - 在您的示例中,它将是数据科学简报。

在更高级别的语句中,现在我们将结果作为 table 字段,我们需要构建一个 jsonb object 并将它们全部聚合到一行。为此,我们使用 jsonb_build_object 向其传递包含以下内容的对:字段名称 + 值。这给我们带来了 3 行数据,每行都有一个单独的 jsonb 列数据。由于我们只需要输出中的一行(聚合 json),因此我们需要在其上应用 jsonb_agg。这为我们带来了您正在寻找的结果。

代码

检查 LIVE DEMO 以查看其工作原理。

select
  jsonb_agg(
    jsonb_build_object('field_type', field_type,
                     'briefings_count', briefings_count,
                     'meetings_count', meetings_count
                     )
    ) as agg_data
from (
  select
      j.k as field_type
    , coalesce(max(case when t.count_type = 'briefings_count' then j.v::int end),0) as briefings_count
    , coalesce(max(case when t.count_type = 'meetings_count'  then j.v::int end),0) as meetings_count
  from tbl t, 
       jsonb_each_text(data) j(k,v)
  group by j.k
  ) t