В чем разница между IN
и ANY
оператором в PostgreSQL?
Рабочий механизм у обоих вроде одинаков. Кто-нибудь может объяснить это на примере?
В чем разница между IN
и ANY
оператором в PostgreSQL?
Рабочий механизм у обоих вроде одинаков. Кто-нибудь может объяснить это на примере?
Ответы:
(Ни и IN
не ANY
является «оператором». «Конструкция» или «элемент синтаксиса».)
По логике , цитируя мануал :
IN
эквивалентно= ANY
.
Но есть два варианта синтаксиса из IN
и два варианта ANY
. Подробности:
IN
взятие набора эквивалентно = ANY
взятию набора , как показано здесь:
Но второй вариант каждого не эквивалентен другому. Второй вариант ANY
конструкции принимает массив (должен быть фактическим типом массива), а второй вариант IN
принимает список значений, разделенных запятыми . Это приводит к различным ограничениям на передачу значений, а также может привести к различным планам запросов в особых случаях:
=any()
но используется сin
ANY
более универсаленANY
Конструкция является гораздо более универсальным, так как он может быть объединен с различными операторами, а не только =
. Пример:
SELECT 'foo' LIKE ANY('{FOO,bar,%oo%}');
Для большого количества значений предоставление набора лучше масштабируется для каждого:
Связанный:
«Найти строки id
в заданном массиве»:
SELECT * FROM tbl WHERE id = ANY (ARRAY[1, 2]);
Инверсия: «Найти строки , в которых id
является не в массиве»:
SELECT * FROM tbl WHERE id <> ALL (ARRAY[1, 2]);
SELECT * FROM tbl WHERE id <> ALL ('{1, 2}'); -- equivalent array literal
SELECT * FROM tbl WHERE NOT (id = ANY ('{1, 2}'));
Все три равнозначны. Первый с конструктором массива , два других с литералом массива . Тип данных может быть однозначно получен из контекста. В противном случае может потребоваться явное приведение, например'{1,2}'::int[]
.
Строки с id IS NULL
не проходят ни одно из этих выражений. Чтобы добавить NULL
значения дополнительно:
SELECT * FROM tbl WHERE (id = ANY ('{1, 2}')) IS NOT TRUE;
SELECT * from mytable where id in (1, 2, 3)
всегда будут те же строки, что и SELECT * from mytable where id = ANY('{1, 2, 3}')
, даже если у них потенциально могут быть разные планы запросов.
ANY
нельзя комбинировать с !=
оператором. Я не думаю, что это задокументировано, но select * from foo where id != ANY (ARRAY[1, 2])
это не то же самое, что select * from foo where id NOT IN (1, 2)
. С другой стороны, select * from foo where NOT (id = ANY (ARRAY[1, 2]))
работает как положено.
ANY
можно комбинировать с !=
оператором. Но это еще не все. Я добавил главу выше. (Обратите внимание, что <>
это оператор в стандартном SQL - хотя !=
он также принят в Postgres.)
NULL
значения? Будет ли WHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;
работать так же хорошо?
(id = ...) IS NOT TRUE
работает, потому что id = ...
оценивает, только TRUE
если есть фактическое совпадение. Результаты FALSE
или NULL
пройдите наш тест. См. Stackoverflow.com/a/23767625/939860 . Добавленные вами тесты выражений для чего-то еще. Это было бы эквивалентноWHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Есть два очевидных момента, а также пункты другого ответа:
Они в точности эквивалентны при использовании подзапросов:
SELECT * FROM table
WHERE column IN(subquery);
SELECT * FROM table
WHERE column = ANY(subquery);
С другой стороны:
Только IN
оператор допускает простой список:
SELECT * FROM table
WHERE column IN(… , … , …);
Предположение, что они точно такие же, несколько раз ловило меня, когда я забывал, что ANY
это не работает со списками.