В чем разница между IN и ANYоператором в PostgreSQL?
Рабочий механизм у обоих вроде одинаков. Кто-нибудь может объяснить это на примере?
В чем разница между IN и ANYоператором в PostgreSQL?
Рабочий механизм у обоих вроде одинаков. Кто-нибудь может объяснить это на примере?
Ответы:
(Ни и INне ANYявляется «оператором». «Конструкция» или «элемент синтаксиса».)
По логике , цитируя мануал :
INэквивалентно= ANY.
Но есть два варианта синтаксиса из INи два варианта ANY. Подробности:
IN взятие набора эквивалентно = ANYвзятию набора , как показано здесь:
Но второй вариант каждого не эквивалентен другому. Второй вариант ANYконструкции принимает массив (должен быть фактическим типом массива), а второй вариант INпринимает список значений, разделенных запятыми . Это приводит к различным ограничениям на передачу значений, а также может привести к различным планам запросов в особых случаях:
=any()но используется сinANY более универсален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это не работает со списками.