Postgres 在 Json 对象数组中的值

时间:2021-03-18 21:31:15

标签: arrays json postgresql

我在 Postgres V11 中工作并且有一个包含 int4 类型字段 (typeid) 的表。

我还有从另一个表中获取并存储到局部变量中的 JSONB 数据。

这个数据看起来像

{"Types":[{"Category": "a", "TypeID": 26}, {"Category": "a", "TypeID": 27}, {"Category": "b", "TypeID": 28}, {"Category": "c", "TypeID": 30}, {"Category": "d", "TypeID": 29}]}

我要编写的查询是

SELECT * FROM table WHERE typeid is contained in this json data

因此,如果 json 数组中列出了 typeid,我只希望返回表中的行。

我尝试了不同的组合,但还没有找到有效的方法。

SELECT * FROM table WHERE typeid @> ANY (jsondata -> 'Types' -> 'TypeID')

jsondata -> 'Types' 似乎只返回数组,但我似乎无法弄清楚如何指定我想与对象中的 TypeID 值进行比较。

Postgres 不断返回

错误:操作 ANY/ALL(数组)需要右侧的数组

所以,我尝试只返回数组,但它不知道要与什么进行比较。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

没有您可以使用的单一运算符。您将需要取消嵌套数组并测试每个元素:

select t.*
from the_table t
where exists (select *
              from jsonb_array_elements(t.jsondata -> 'Types') as j(element)
              where j.element ? 'TypeID')

这将列出至少一个数组元素包含 TypeID 的行。

答案 1 :(得分:0)

ANY 采用 PostgreSQL 数组,而不是 JSON 数组。因为 JSON 数组可以具有异构类型,所以它们不能简单地转换为 PostgreSQL 数组。您可以创建一个帮助函数来进行这种转换。

create function jsonb_to_intarray(jsonb,property text) returns int[] immutable parallel safe language SQL as $$
  select array_agg((x->>$2)::int) from jsonb_array_elements($1) f(x)
$$;

然后:

SELECT * FROM table WHERE typeid =ANY (jsonb_to_intarray(jsondata -> 'Types', 'TypeID'));