如何在postgresql中将两行转换为键值json对象?

can*_*sik 2 sql postgresql json key-value

我有一个像下面这样的数据模型,它被简化为只显示这个问题(底部的SQL Fiddle Link):

在此输入图像描述

人在数据库中表示为具有名称和多个属性的元表行,这些属性作为键值对存储在数据表中(键和值在单独的列中).

预期结果

现在我想检索具有所有属性的所有用户.属性应作为json对象返回到单独的列中.例如:

name, data
Florian, { "age":23, "color":"blue" }
Markus, { "age":24, "color":"green" }
Run Code Online (Sandbox Code Playgroud)

我的方法

现在我的问题是,我找不到在postgres中创建键值对的方法.我试过以下:

SELECT
  name,
  array_to_json(array_agg(row(d.key, d.value))) AS data
FROM meta AS m
JOIN (
  SELECT d.fk_id, d.key, d.value AS value FROM data AS d
  ) AS d
ON d.fk_id = m.id
GROUP BY m.name;
Run Code Online (Sandbox Code Playgroud)

但它将此作为数据列返回:

[{"f1":"age","f2":24},{"f1":"color","f2":"blue"}]
Run Code Online (Sandbox Code Playgroud)

其他方案

我知道有一个函数crosstab可以让我将数据表转换为一个键作为列和值作为行表.但这不是动态的.我不知道一个人在数据表中有多少属性.所以这不是一个选择.

我还可以使用两个行值创建一个类似json的字符串并聚合它们.但也许有一个更好的解决方案.

不,由于真实数据模型已经在多方使用,因此无法更改数据模型.

SQLFiddle

检查并测试我为此问题创建的小提琴:http: //sqlfiddle.com/#!15/bd579/14

kli*_*lin 6

试试这个:

select 
    name, 
    json_object(array_agg(key), array_agg(replace(value::text, '"', ''))) as data
from data
join meta on fk_id = id
group by 1
Run Code Online (Sandbox Code Playgroud)

函数json_object(keys text[], values text[])Postgres 9.4中引入.