PostgreSQL: можно ли определить, перекрывают ли какие-либо элементы массива диапазон? - PullRequest
0 голосов
/ 19 октября 2019

Допустим, у меня есть таблица со столбцом int[] и значениями:

'[1,4,1300]'::int4[]

Я хочу иметь возможность запросить столбец и получить true, если ЛЮБОЙэлементов совпадают с оператором BETWEEN. Так, в этом случае, что-то вроде:

SELECT id FROM table WHERE col && '[1000,2000]'::int4range или аналогичное.

В столбце используется gist__int_ops

Ответы [ 3 ]

1 голос
/ 19 октября 2019

Вы можете использовать диапазон с оператором , например:

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($1), upper($1)- 1) i)
$$;

select id
from my_table 
where col && int_range_to_array('[2,4]');

Очевидно, что производительность зависит от размеров диапазона.

1 голос
/ 20 октября 2019

Догматичный ответ: вы не должны использовать массивы в своих таблицах, а вместо этого должны использовать дочерние таблицы. Я обычно не придерживаюсь догмы, но в этом случае я думаю, что это, вероятно, и прагматичный ответ. Я не вижу ничего в API расширяемости для индексов, который выглядит так, как будто вы могли бы даже реализовать собственное расширение для этого.

Если вы используете дочернюю таблицу, вы вернетесь к использованию BETWEEN..AND для своегозапрос, а не int4range, чтобы получить индексируемость.

0 голосов
/ 19 октября 2019

Вы можете unnest():

where exists (select 1
              from unnest(col) u(val)
              where u.val between 2 and 4
             )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...