我在 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(数组)需要右侧的数组
所以,我尝试只返回数组,但它不知道要与什么进行比较。
感谢您的帮助!
答案 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'));