【问题标题】:Query for multiple array elements in Postgres JSONB column在 Postgres JSONB 列中查询多个数组元素
【发布时间】:2021-05-12 19:55:06
【问题描述】:

我有一个表 mydata jsonb 列,其中包含一个整数数组。

create table mydata
(
    name varchar,
    data jsonb
);

这是一些测试数据:

insert into mydata (name, data)
VALUES
('hello1', '[1]'),
('hello12', '[1,2]'),
('hello2', '[2]'),
('hello23', '[2,3]')
;

我现在想在表格中查询“数据”中包含 2 或 3(或两者)的元素。 除此之外还有更好的语法:

select * from mydata where (data @> '2' or data @> '3');

因为我当然可能有超过 2 个选项要查询。我假设我能够执行这样的子查询(不起作用,就像提示我想要实现的目标一样):


create table other ( id bigserial , text varchar);
insert into other (id, text) values (1, 'x'), (2, 'y'), (3, 'y'), (4, 'z');

我现在要做的是,从 mydata 中获取所有数据,其中 data 引用了 other_table

select * from mydata where (data @> IN (select distinct id from other_table where text='y'));

非常感谢, 弗里茨

【问题讨论】:

  • 在您的问题中,您声明您想要包含“2 3”的元素 - 可以读取它不应该返回包含两者的元素 - 但是不是您查询的内容。如果您确实还想包含包含两个值的元素,那么使用原生数组很容易,因为它支持重叠运算符 && - 但 JSONB 不支持。
  • @a_horse_with_no_name 很抱歉造成误解:我想要所有具有 2 或 3 或两者的条目。将更新描述
  • 如果您只在该列中存储整数,我建议使用int[] 而不是jsonb,那么这种类型的查询更容易(where data && array[2,3]
  • @a_horse_with_no_name:是的,谢谢!对于这个非常具体的用例,这是完美的。即使有子查询:``` select * from mydata where data && array(select id from other where text = 'y'); ```(假设数据现在有数据类型 bigint[] 谢谢

标签: arrays postgresql jsonb


【解决方案1】:

step-by-step demo:db<>fiddle

SELECT DISTINCT                             -- 3
    name,
    data
FROM mydata,
   jsonb_array_elements_text(data) elems    -- 1
WHERE value::int IN (
    SELECT id FROM other WHERE "text" = 'y' -- 2
)
  1. 将所有数组元素提取到自己的记录中
  2. 过滤以前的元素是否是子查询的元素
  3. 因为此过滤器可能会返回相同的记录两次(如果原始数据同时匹配,23DISTINCT 确保返回唯一的记录。

【讨论】:

  • 谢谢。这仍然需要手动将我要查询的所有条目放入列表中。我想要一个返回任意数量结果的子查询。这可能吗?
  • 我不清楚你想要实现什么...请在问题中添加一些示例数据和预期输出
  • 用第二个示例表更新了问题。现在应该很清楚了。
【解决方案2】:

如果 ID 来自不同的表,您可以执行以下操作:

select *
from mydata m
where exists (select *
              from other o
              where o.id in (select v::int 
                             from jsonb_array_elements_text(m.data) as x(v)))

使用 Postgres 12 或更高版本,您可以使用

select *
from mydata m
where exists (select *
              from other o
              where jsonb_path_exists(m.data, '$[*] ? (@ == $id)', jsonb_build_object('id', o.id)))

不确定哪一个会更快。

【讨论】:

    猜你喜欢
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 2021-01-08
    相关资源
    最近更新 更多