Select JSON 来自 EAV 结构结果集的值
Select JSON value from a EAV structure result set
给定 EAV 结构中的结果集,例如:
id | attributeName | stringValue | intValue | BooleanValue
---------------------------------------------------------------
1 stringFoo v1
1 stringFooList v2
1 stringFooList v3
1 intFoo 10
1 intFooList 10
1 intFooList 20
1 booleanFoo true
1 booleanFooList true
1 booleanFooList true
如何 select 将所有属性和值对作为 JSON/JSONB 格式的单个值,类似于:
{
"stringFoo" : "v1" ,
"stringFooList" : ["v2","v3"] ,
"intFoo" : 10 ,
"intFooList" : [10,20],
"booleanFoo" : true,
"booleanFooList" : [true,true]
}
如果一个属性有多个属性值,例如 stringFooList
,它会将其格式化为 JSON 数组。
我正在使用 PostgreSQL 9.6
你可以这样做:
select id, jsonb_object_agg(att, value)
from (
select id,
attributename as att,
case
when count(*) > 1 then
jsonb_agg(coalesce(stringvalue,intvalue::text,booleanvalue::text))
else
to_jsonb(min(coalesce(stringvalue,intvalue::text,booleanvalue::text)))
end as value
from eav
group by id, attributename
) t
group by id;
内部 select 将多个值聚合成一个 JSON 数组,将单个值聚合成 JSON 标量值。然后外部查询构建所有行的单个 JSON 值。
@a_horse_with_no_name
的回答给了我一个好的开始。我扩展 his/her 答案并提出以下查询,以便 JSON 数组中的元素具有与 PostgreSQL 中定义的相同的数据类型。
select id, jsonb_object_agg(att,
case
when strval is not null then strval
when intvalue is not null then intvalue
else boolVal
end
)
from (
select id,
attributename as att,
case when count(*) > 1 then
jsonb_agg(stringvalue) filter (where stringvalue is not null)
else
to_jsonb(min(stringvalue) filter (where stringvalue is not null))
end as strVal,
case when count(*) > 1 then
jsonb_agg(intvalue) filter (where intvalue is not null)
else
to_jsonb(min(intvalue) filter (where intvalue is not null))
end as intvalue,
case when count(*) > 1 then
jsonb_agg(booleanvalue) filter (where booleanvalue is not null)
else
to_jsonb(bool_and(booleanvalue) filter (where booleanvalue is not null))
end as boolVal
from eav
group by id, attributename
) t
group by id;
给定 EAV 结构中的结果集,例如:
id | attributeName | stringValue | intValue | BooleanValue
---------------------------------------------------------------
1 stringFoo v1
1 stringFooList v2
1 stringFooList v3
1 intFoo 10
1 intFooList 10
1 intFooList 20
1 booleanFoo true
1 booleanFooList true
1 booleanFooList true
如何 select 将所有属性和值对作为 JSON/JSONB 格式的单个值,类似于:
{
"stringFoo" : "v1" ,
"stringFooList" : ["v2","v3"] ,
"intFoo" : 10 ,
"intFooList" : [10,20],
"booleanFoo" : true,
"booleanFooList" : [true,true]
}
如果一个属性有多个属性值,例如 stringFooList
,它会将其格式化为 JSON 数组。
我正在使用 PostgreSQL 9.6
你可以这样做:
select id, jsonb_object_agg(att, value)
from (
select id,
attributename as att,
case
when count(*) > 1 then
jsonb_agg(coalesce(stringvalue,intvalue::text,booleanvalue::text))
else
to_jsonb(min(coalesce(stringvalue,intvalue::text,booleanvalue::text)))
end as value
from eav
group by id, attributename
) t
group by id;
内部 select 将多个值聚合成一个 JSON 数组,将单个值聚合成 JSON 标量值。然后外部查询构建所有行的单个 JSON 值。
@a_horse_with_no_name
的回答给了我一个好的开始。我扩展 his/her 答案并提出以下查询,以便 JSON 数组中的元素具有与 PostgreSQL 中定义的相同的数据类型。
select id, jsonb_object_agg(att,
case
when strval is not null then strval
when intvalue is not null then intvalue
else boolVal
end
)
from (
select id,
attributename as att,
case when count(*) > 1 then
jsonb_agg(stringvalue) filter (where stringvalue is not null)
else
to_jsonb(min(stringvalue) filter (where stringvalue is not null))
end as strVal,
case when count(*) > 1 then
jsonb_agg(intvalue) filter (where intvalue is not null)
else
to_jsonb(min(intvalue) filter (where intvalue is not null))
end as intvalue,
case when count(*) > 1 then
jsonb_agg(booleanvalue) filter (where booleanvalue is not null)
else
to_jsonb(bool_and(booleanvalue) filter (where booleanvalue is not null))
end as boolVal
from eav
group by id, attributename
) t
group by id;