can*_*sik 11 postgresql json postgresql-9.4
人在数据库中表示为具有名称和多个属性的元表行,这些属性作为键值对存储在数据表中(键和值在单独的列中).
简化的数据模型
现在有一个查询来检索所有用户(名称)及其所有属性(数据).这些属性在单独的列中作为JSON对象返回.这是一个例子:
name data
Florian { "age":25 }
Markus { "age":25, "color":"blue" }
Thomas {}
Run Code Online (Sandbox Code Playgroud)
SQL命令如下所示:
SELECT
name,
json_object_agg(d.key, d.value) AS data,
FROM meta AS m
JOIN (
JOIN 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)
现在我遇到的问题是,像托马斯这样没有任何属性存储在键值表中的用户没有用我的select函数显示.这是因为它只做了一次JOIN,没有LEFT OUTER JOIN.
如果我会使用LEFT OUTER JOIN然后我遇到问题,json_object_agg尝试聚合NULL值并死于错误.
所以我试着检查一个用户的键列是否NULL返回一个空数组,这样json_object_agg就可以创建一个空的JSON对象.
但实际上并没有在SQL中创建空数组的功能.我找到的最接近的是这个:
select '{}'::text[];
Run Code Online (Sandbox Code Playgroud)
与COALESCE查询结合使用如下所示:
json_object_agg(COALESCE(d.key, '{}'::text[]), COALESCE(d.value, '{}'::text[])) AS data
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试使用它,我会收到以下错误:
ERROR: COALESCE types text and text[] cannot be matched
LINE 10: json_object_agg(COALESCE(d.key, '{}'::text[]), COALES...
^
Query failed
PostgreSQL said: COALESCE types text and text[] cannot be matched
Run Code Online (Sandbox Code Playgroud)
所以看起来在运行时d.key是单个值而不是数组.
所以我试着采取json_object_agg并替换它json_object不会为我聚合键:
json_object(COALESCE(array_agg(d.key), '{}'::text[]), COALESCE(array_agg(d.value), '{}'::text[])) AS data
Run Code Online (Sandbox Code Playgroud)
但是我得到了错误null value not allowed for object key.所以COALESCE不检查数组是否为空.
那么,是否有一个函数来检查连接列是否为空,如果是,则只返回一个简单的JSON对象?
或者还有其他解决方案可以解决我的问题吗?
kli*_*lin 21
使用left join带coalesce().作为默认值使用'{}'::json.
select name, coalesce(d.data, '{}'::json) as data
from meta m
left join (
select fk_id, json_object_agg(d.key, d.value) as data
from data d
group by 1
) d
on m.id = d.fk_id;
name | data
---------+------------------------------------
Florian | { "age" : "25" }
Marcus | { "age" : "25", "color" : "blue" }
Thomas | {}
(3 rows)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12607 次 |
| 最近记录: |