Проверьте, существует ли значение в массиве Postgres
Мне нужен способ проверить, существует ли значение в заданном массиве. До сих пор я придумал что-то вроде этого
select '{1,2,3}'::int[] @> (ARRAY[]::int[] || value_variable::int)
но я продолжаю думать, что должен быть более простой способ этого, я просто не могу его увидеть.
Изменить: просто понял, что я могу это сделать
select '{1,2,3}'::int[] @> ARRAY[value_variable::int]
Это намного лучше, и я считаю, что этого хватит, но если у вас есть другие способы сделать это, пожалуйста, поделитесь.
Ответы
Ответ 1
Упрощение с помощью ANY
:
SELECT value_variable = ANY ('{1,2,3}'::int[])
Правильный операнд ANY
(между круглыми скобками) может быть либо set (результат подзапроса, например), либо < массив href= "http://www.postgresql.org/docs/current/interactive/functions-comparisons.html#AEN19712" rel= "noreferrer" > . Существует несколько способов его использования:
Важная разница: Операторы массива (<@
, @>
и др.) ожидают типы массивов как операнды и поддерживают индексы GIN или GiST в стандартном распределении PostgreSQL, а конструкция ANY
ожидает, что тип элемента будет левым операндом и не будет поддерживать эти индексы. Пример:
Ничего из этого не работает для элементов NULL
. Проверить NULL
:
Ответ 2
Следите за ловушкой, в которую я попал: проверяя, нет ли определенного значения в массиве, вы не должны делать:
SELECT value_variable != ANY('{1,2,3}'::int[])
но используйте
SELECT value_variable != ALL('{1,2,3}'::int[])
вместо.
Ответ 3
но если у вас есть другие способы сделать это, пожалуйста, поделитесь.
Вы можете сравнить два массива. Если какое-либо из значений в левом массиве перекрывает значения в правильном массиве, оно возвращает true. Это своего рода хакерство, но оно работает.
SELECT '{1}' && '{1,2,3}'::int[]; -- true
SELECT '{1,4}' && '{1,2,3}'::int[]; -- true
SELECT '{4}' && '{1,2,3}'::int[]; -- false
- В первом и втором запросах значение
1
находится в правильном массиве
- Обратите внимание, что второй запрос
true
, хотя значение 4
не содержится в правильном массиве
- Для третьего запроса в правом массиве нет значений (т.е.
4
), поэтому он возвращает false
Ответ 4
unnest
.
Он расширяет массив до набора строк, а затем просто проверка значения существует или нет, так же просто, как использование IN
или NOT IN
.
например.
select * from table where id NOT IN (select unnest(exception_list_ids) from table2)
Ответ 5
При поиске существования элемента в массиве требуется правильное кастинг для передачи парсера SQL postgres. Вот один пример запроса с использованием массива содержит оператор в предложении join:
Для простоты я перечисляю только соответствующую часть:
table1 other_name text[]; -- is an array of text
Часть соединения SQL, показанная
from table1 t1 join table2 t2 on t1.other_name::text[] @> ARRAY[t2.panel::text]
Также работает
on t2.panel = ANY(t1.other_name)
Я просто догадываюсь, что требуется дополнительное кастинг, потому что для синтаксического анализа не нужно отображать определение таблицы для определения точного типа столбца. Другие, пожалуйста, прокомментируйте это.