提问人:0x55b1E06FF 提问时间:10/29/2023 最后编辑:Erwin Brandstetter0x55b1E06FF 更新时间:10/29/2023 访问量:66
从 JSONB 列中的多个嵌套数组中提取值
Extract values from multiple nested arrays in a JSONB column
问:
我目前正在处理一个PostgreSQL查询,以从JSONB列中提取特定值。这是我正在使用的查询:
select
a.id,
(jsonb_array_elements(a.info->'attribute1')->>'value') as attribute1,
(a.info->>'attribute2') as attribute2,
(a.info->>'attribute3') as attribute3,
(jsonb_array_elements(a.info->'attribute4')->>'value') as attribute4
from a_table a
where
(cast(a.info->>'attribute3' as NUMERIC) > 0
or jsonb_array_length(a.info->'attribute1') > 0
or jsonb_array_length(a.info->'attribute4') > 0
or cast(a.info->>'attribute2' as NUMERIC) > 0)
and a.active=true
and a.data='AAA0000'
我面临的问题是,它复制的次数与(或具有更多寄存器的任何其他属性)一样多,当我使用此查询作为子查询来对所有列的值求和时,会产生不正确的结果。attribute3
attribute1
此查询的结果如下:
下面是上一个结果的信息列中的数据示例。可以看出,前面的结果对于 attribute3 是不正确的。
{
"attribute1": [{"value": 30.45, "description": "abc1"}, {"value": 5, "description": "abc2"}, {"value": 5, "description": "abc3"}],
"attribute2": 0,
"attribute3": 69.36,
"attribute4": [{"value": 18, "description": "aaa"}]
}
我正在寻找一种方法来修改查询以防止复制属性值。
答:
2赞
Erwin Brandstetter
10/29/2023
#1
避免这种行相乘的一种方法是将每个生成的集合聚合到单个数组中。喜欢:
SELECT a.id
, ARRAY(SELECT (jsonb_array_elements(a.info -> 'attribute1') ->> 'value')::numeric) AS attribute1
, (a.info ->> 'attribute2')::numeric AS attribute2
, (a.info ->> 'attribute3')::numeric AS attribute3
, ARRAY(SELECT (jsonb_array_elements(a.info -> 'attribute4') ->> 'value')::numeric) AS attribute4
FROM ...
否则,您将获得与最大数组包含元素一样多的行 - 在 Postgres 10 或更高版本中。看:
您需要强制转换为“将所有列的值相加”。因此,此替代方法汇总了每个数组中的值:numeric
SELECT a.id
, (SELECT sum((a1.elem ->> 'value')::numeric) FROM jsonb_array_elements(a.info -> 'attribute1') a1(elem)) AS attribute1
, (a.info ->> 'attribute2')::numeric AS attribute2
, (a.info ->> 'attribute3')::numeric AS attribute3
, (SELECT sum((a4.elem ->> 'value')::numeric) FROM jsonb_array_elements(a.info -> 'attribute4') a4(elem)) AS attribute4
FROM ...
1赞
jjanes
10/29/2023
#2
如果只想填充 NULL 值,则可以将标量条目包装到虚拟数组中,然后像执行“自然”数组一样取消嵌套。所以第 4 行变成:
jsonb_array_elements(jsonb_build_array(a.info->'attribute2')) as attribute2,
评论