Jaka jest różnica między operatorem IN
i ANY
w PostgreSQL?
Mechanizm działania obu wydaje się być taki sam. Czy ktoś może to wyjaśnić na przykładzie?
Jaka jest różnica między operatorem IN
i ANY
w PostgreSQL?
Mechanizm działania obu wydaje się być taki sam. Czy ktoś może to wyjaśnić na przykładzie?
Odpowiedzi:
(Ani „operator”, IN
ani ANY
„ nie jest”. „Konstrukcja” lub „element składni”).
Logicznie , cytując instrukcję :
IN
jest równoważne= ANY
.
Ale istnieją dwa warianty składniowe z IN
i dwa warianty ANY
. Detale:
IN
zabranie zestawu jest równoznaczne z = ANY
wzięciem zestawu , jak pokazano tutaj:
Ale drugi wariant każdego z nich nie jest równoważny z drugim. Drugi wariant ANY
konstrukcji przyjmuje tablicę (musi być rzeczywistym typem tablicy), podczas gdy drugi wariant IN
przyjmuje listę wartości oddzielonych przecinkami . Prowadzi to do różnych ograniczeń w przekazywaniu wartości i może również prowadzić do różnych planów zapytań w szczególnych przypadkach:
=any()
ale używany zin
ANY
jest bardziej wszechstronnyANY
Konstrukcja jest bardziej uniwersalny, ponieważ mogą one być połączone z różnymi operatorami, nie tylko =
. Przykład:
SELECT 'foo' LIKE ANY('{FOO,bar,%oo%}');
W przypadku dużej liczby wartości zapewnienie zestawu skal dla każdej z nich jest lepsze:
Związane z:
„Znajdź wiersze, w których id
znajduje się podana tablica”:
SELECT * FROM tbl WHERE id = ANY (ARRAY[1, 2]);
Inwersja: „Znajdź wiersze, których nieid
ma w tablicy”:
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}'));
Wszystkie trzy równoważne. Pierwsza z konstruktorem tablicy , pozostałe dwie z literałem tablicowym . Typ danych można jednoznacznie wyprowadzić z kontekstu. W przeciwnym razie może być wymagana wyraźna obsada, na przykład '{1,2}'::int[]
.
Wiersze z id IS NULL
nie przechodzą żadnego z tych wyrażeń. Aby NULL
dodatkowo uwzględnić wartości:
SELECT * FROM tbl WHERE (id = ANY ('{1, 2}')) IS NOT TRUE;
SELECT * from mytable where id in (1, 2, 3)
zawsze będą powodować te same wiersze, co SELECT * from mytable where id = ANY('{1, 2, 3}')
, nawet jeśli potencjalnie mogą mieć różne plany zapytań.
ANY
nie można łączyć z !=
operatorem. Myślę, że nie jest to udokumentowane, ale select * from foo where id != ANY (ARRAY[1, 2])
to nie to samo, co select * from foo where id NOT IN (1, 2)
. Z drugiej strony select * from foo where NOT (id = ANY (ARRAY[1, 2]))
działa zgodnie z oczekiwaniami.
ANY
można łączyć z !=
operatorem. Ale to nie wszystko. Dodałem rozdział powyżej. (Zauważ, że <>
jest to operator w standardowym SQL - choć !=
jest również akceptowany w Postgres.)
NULL
wartości? Działałby WHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;
równie dobrze?
(id = ...) IS NOT TRUE
działa, ponieważ wartościowane są id = ...
tylko TRUE
wtedy, gdy istnieje rzeczywiste dopasowanie. Wyniki FALSE
lub NULL
zdaj nasz test. Zobacz: stackoverflow.com/a/23767625/939860 . Twoje dodane wyrażenie sprawdza coś innego. To byłoby równoważneWHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Istnieją dwa oczywiste punkty, a także punkty w drugiej odpowiedzi:
Są dokładnie równoważne podczas korzystania z zapytań podrzędnych:
SELECT * FROM table
WHERE column IN(subquery);
SELECT * FROM table
WHERE column = ANY(subquery);
Z drugiej strony:
Tylko IN
operator umożliwia prostą listę:
SELECT * FROM table
WHERE column IN(… , … , …);
Zakładanie, że są dokładnie takie same, przyłapało mnie kilka razy, kiedy zapominałem, że ANY
to nie działa w przypadku list.