1

我想知道是否可以将 json 对象“转换”到 json 数组以迭代混合数据集。

我有两行看起来像

{Data:{BASE:{B1:0,color:green}}}
{Data:{BASE:[{B1:1,color:red},{B1:0,color:blue}]}}

我想从所有这些行中提取 B1 val,但我有点受阻:)

我的第一次尝试是 json_extract_array,但它在第一行(不是数组)失败。然后我的第二次尝试是带有案例的 json_array_length ,但在第一行失败(不是数组)

我可以以任何方式处理这种情况吗?基本上我需要提取一个 json 数组(或对象)中 B1 > 0 的所有行,并可能返回包含 B1 > 0 的节点。

4

3 回答 3

3

您的主要问题是您混合了json -> 'Data' -> 'BASE'路径下的数据类型,这不容易处理。我可以想出一个解决方案,但你应该修复你的架构,f.ex。仅包含该路径处的数组。

with v(j) as (
  values (json '{"Data":{"BASE":{"B1":0,"color":"green"}}}'),
         ('{"Data":{"BASE":[{"B1":1,"color":"red"},{"B1":0,"color":"blue"}]}}')
)
select j, node
from v,
lateral (select j #> '{Data,BASE}') b(b),
lateral (select substring(trim(leading E'\x20\x09\x0A\x0D' from b::text) from 1 for 1)) l(l),
lateral (select case
  when l = '{' and (b #>> '{B1}')::numeric > 0 then b
  when l = '[' then (select e from json_array_elements(b) e where (e #>> '{B1}')::numeric > 0 limit 1)
  else null
end) node(node)
where node is not null

SQLFiddle

于 2014-07-04T10:15:17.290 回答
1

返回至少一个对象具有的行B1 > 0

select *
from t
where true in (
    select (j ->> 'B1')::int > 0
    from json_array_elements (json_column -> 'Data' -> 'BASE') s (j)
)
于 2014-07-04T09:54:38.247 回答
0

在此处其他答案的帮助下,我做到了:

with v(j) as (
  values (json '{"Data":{"BASE":{"B1":0,"color":"green"}}}'),
         ('{"Data":{"BASE":[{"B1":1,"color":"red"},{"B1":0,"color":"blue"}]}}')
)
select j->'Data'->'BASE'->>'B1' as "B1"
from v 
where j->'Data'->'BASE'->>'B1' is not null
union all
select json_array_elements(j->'Data'->'BASE')->>'B1'
from v
where j->'Data'->'BASE'->>'B1' is null

将其分为两个查询,一个仅在只有一个值时获取单个值,另一个在有多个时解包数组,null如果您请求数组的文本,则利用 PostgreSQL 返回。然后,我只是合并了两个查询的结果,结果是:

 ------
|  B1  |
 ------
|  0   |
|  1   |
|  0   |
于 2016-03-08T09:35:17.460 回答