根据公共列值将多行合并为一个 JSON 对象

combine more than one rows into a single JSON Object based on common column value

我有以下 table :

id |   model    |  version   |   status
_________________________________________

.. |  model1    |   1.0      |    old
.. |  model1    |   2.0      |    new
.. |  model2    |   1.1      |    old
.. |  model2    |   1.2      |    new

我需要根据同一模型的状态生成 JSON 对象(将两行组合成单个 JSON 对象),如下所示:

[
   {
      "model" : "model1",
      "old_version" : "1.0",
      "new_version" : "2.0"
   },
   {
      "model" : "model2",
      "old_version" : "1.1",
      "new_version" : "1.2"
   }
]

到目前为止我尝试了什么:

select json_agg(json_build_object(t."model",
                                  CASE WHEN t."status" == 'new'
                                   THEN 'new_version',t."version",
                                  end 
                                   CASE WHEN t."status" == 'old'
                                   THEN 'old_version',t."version",
                                  end ))
from (// my select query with various conditions goes here) t

我也遇到语法错误。我怎样才能达到预期的输出

提前致谢!!

CASE 表达式的 THEN 部分只能包含一个表达式,因此 then value_a, value_b end 无效。您还缺少 model 值的键。

但是,这里有一个两阶段聚合:首先聚合每个模型的版本,然后将该结果聚合到一个数组中。由于无法嵌套聚合函数,因此您需要派生的 table 为此:

这汇总了每个模型的版本:

select jsonb_build_object('model', model)||jsonb_object_agg(status||'_version', version)
from (...)
group by model

如果您不能或不想使用状态名称作为“版本密钥”的前缀,则必须使用 CASE 表达式:

select jsonb_build_object('model', model)|| 
              jsonb_object_agg(case status 
                                 when 'old' then 'old_version' 
                                 when 'new' then 'new_version' 
                               end, 
                               version)
from (...)
group by model

然后可以在派生的 table 中使用它来获取 json 数组:

select jsonb_agg(model)
from (
  select jsonb_build_object('model', model)||jsonb_object_agg(status||'_version', version) as model
  from (...)
  group by model
) t

Online example