PostgreSQL:是否可以确定数组中的任何元素是否与范围重叠?
PostgreSQL: Is it possible to determine if any elements in an array overlap a range?
假设我有一个包含 int[]
列和值的 table:
'[1,4,1300]'::int4[]
我希望能够查询该列并在任何元素与 BETWEEN
语句匹配时获得 true
。所以,在这种情况下,类似于:
SELECT id FROM table WHERE col && '[1000,2000]'::int4range
或类似的。
该列使用gist__int_ops
你可以unnest()
:
where exists (select 1
from unnest(col) u(val)
where u.val between 2 and 4
)
您可以使用 containment operator 的范围,例如:
select id
from my_table
where '[2,4]'::int4range @> any(col)
很遗憾,查询没有使用索引。我认为您找不到执行此操作的查询(无需定义您自己的运算符)。
更新。您可以尝试将范围转换为数组。
create or replace function int_range_to_array(int4range)
returns int[] language sql immutable as $$
select array(
select i
from generate_series(lower(), upper()- 1) i)
$$;
select id
from my_table
where col && int_range_to_array('[2,4]');
显然,性能取决于范围大小。
教条式的答案是您不应该在 table 中使用数组,而应该使用子 table 中的数组。我通常不遵守教条,但在这种情况下,我认为这也可能是务实的答案。我在索引的可扩展性 API 中没有看到任何看起来您甚至可以实现自己的扩展来执行此操作的内容。
如果您使用子 table,您将返回使用 BETWEEN..AND
进行查询,而不是 int4range,以获得可索引性。
假设我有一个包含 int[]
列和值的 table:
'[1,4,1300]'::int4[]
我希望能够查询该列并在任何元素与 BETWEEN
语句匹配时获得 true
。所以,在这种情况下,类似于:
SELECT id FROM table WHERE col && '[1000,2000]'::int4range
或类似的。
该列使用gist__int_ops
你可以unnest()
:
where exists (select 1
from unnest(col) u(val)
where u.val between 2 and 4
)
您可以使用 containment operator 的范围,例如:
select id
from my_table
where '[2,4]'::int4range @> any(col)
很遗憾,查询没有使用索引。我认为您找不到执行此操作的查询(无需定义您自己的运算符)。
更新。您可以尝试将范围转换为数组。
create or replace function int_range_to_array(int4range)
returns int[] language sql immutable as $$
select array(
select i
from generate_series(lower(), upper()- 1) i)
$$;
select id
from my_table
where col && int_range_to_array('[2,4]');
显然,性能取决于范围大小。
教条式的答案是您不应该在 table 中使用数组,而应该使用子 table 中的数组。我通常不遵守教条,但在这种情况下,我认为这也可能是务实的答案。我在索引的可扩展性 API 中没有看到任何看起来您甚至可以实现自己的扩展来执行此操作的内容。
如果您使用子 table,您将返回使用 BETWEEN..AND
进行查询,而不是 int4range,以获得可索引性。