Was ist der Unterschied zwischen INund ANYOperator in PostgreSQL?
Der Arbeitsmechanismus beider scheint der gleiche zu sein. Kann jemand dies mit einem Beispiel erklären?
Aber die zweite Variante von jedem ist nicht gleichbedeutend mit der anderen. Die zweite Variante des ANYKonstrukts verwendet ein Array (muss ein tatsächlicher Array-Typ sein), während die zweite Variante INeine durch Kommas getrennte Liste von Werten verwendet . Dies führt zu unterschiedlichen Einschränkungen bei der Übergabe von Werten und kann in besonderen Fällen auch zu unterschiedlichen Abfrageplänen führen:
"Suchen Sie Zeilen, in denen idsich das angegebene Array befindet":
SELECT*FROM tbl WHERE id =ANY(ARRAY[1,2]);
Inversion: "Zeilen suchen, die idsich nicht im Array befinden":
SELECT*FROM tbl WHERE id <>ALL(ARRAY[1,2]);SELECT*FROM tbl WHERE id <>ALL('{1, 2}');-- equivalent array literalSELECT*FROM tbl WHERENOT(id =ANY('{1, 2}'));
Alle drei gleichwertig. Der erste mit Array-Konstruktor , die anderen beiden mit Array-Literal . Der Datentyp kann eindeutig aus dem Kontext abgeleitet werden. Andernfalls kann eine explizite Besetzung erforderlich sein, wie z '{1,2}'::int[].
Zeilen mit übergeben id IS NULLkeinen dieser Ausdrücke. Um NULLWerte zusätzlich aufzunehmen:
Es wäre schön, explizit zu verdeutlichen, dass die Ergebnisse der zweiten Varianten immer gleich sein werden. Ich bin mir zu 99% sicher, dass dies tatsächlich der Fall ist, aber die Antwort scheint es nicht zu sagen. SELECT * from mytable where id in (1, 2, 3)Dies bedeutet, dass immer dieselben Zeilen wie angezeigt werden SELECT * from mytable where id = ANY('{1, 2, 3}'), auch wenn sie möglicherweise unterschiedliche Abfragepläne haben.
KPD
1
ANYkann nicht mit dem !=Bediener kombiniert werden. Ich denke nicht, dass es dokumentiert ist, aber es select * from foo where id != ANY (ARRAY[1, 2])ist nicht dasselbe wie select * from foo where id NOT IN (1, 2). Funktioniert dagegen select * from foo where NOT (id = ANY (ARRAY[1, 2]))wie erwartet.
Qris
1
@qris: ANYkann mit dem !=Operator kombiniert werden. Aber es steckt noch mehr dahinter. Ich habe oben ein Kapitel hinzugefügt. (Beachten Sie, dass dies <>der Operator in Standard-SQL ist - obwohl dies !=auch in Postgres akzeptiert wird.)
Erwin Brandstetter
Wie funktioniert die letzte Version, die NULLWerte enthält ? Würde WHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;genauso gut funktionieren?
dvtan
1
@dvtan: (id = ...) IS NOT TRUEfunktioniert, weil id = ...nur ausgewertet wird, TRUEob eine tatsächliche Übereinstimmung vorliegt . Ergebnisse FALSEoder NULLbestehen Sie unseren Test. Siehe: stackoverflow.com/a/23767625/939860 . Ihr hinzugefügter Ausdruck testet auf etwas anderes. Dies wäre gleichwertigWHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Erwin Brandstetter
3
Es gibt zwei offensichtliche Punkte sowie die Punkte in der anderen Antwort:
Sie sind bei Verwendung von Unterabfragen genau gleichwertig:
Antworten:
(Weder
IN
nochANY
ist ein "Operator". Ein "Konstrukt" oder "Syntaxelement".)Logisch , zitiert das Handbuch :
Es gibt jedoch zwei Syntaxvarianten von
IN
und zwei Varianten vonANY
. Einzelheiten:IN
Das Nehmen eines Sets entspricht dem= ANY
Nehmen eines Sets , wie hier gezeigt:Aber die zweite Variante von jedem ist nicht gleichbedeutend mit der anderen. Die zweite Variante des
ANY
Konstrukts verwendet ein Array (muss ein tatsächlicher Array-Typ sein), während die zweite VarianteIN
eine durch Kommas getrennte Liste von Werten verwendet . Dies führt zu unterschiedlichen Einschränkungen bei der Übergabe von Werten und kann in besonderen Fällen auch zu unterschiedlichen Abfrageplänen führen:=any()
aber verwendet mitin
ANY
ist vielseitigerDas
ANY
Konstrukt ist weitaus vielseitiger, da es nicht nur mit verschiedenen Operatoren kombiniert werden kann=
. Beispiel:Für eine große Anzahl von Werten ist die Bereitstellung eines Satzes für jeden Wert besser:
Verbunden:
Inversion / Gegenteil / Ausschluss
"Suchen Sie Zeilen, in denen
id
sich das angegebene Array befindet":Inversion: "Zeilen suchen, die
id
sich nicht im Array befinden":Alle drei gleichwertig. Der erste mit Array-Konstruktor , die anderen beiden mit Array-Literal . Der Datentyp kann eindeutig aus dem Kontext abgeleitet werden. Andernfalls kann eine explizite Besetzung erforderlich sein, wie z
'{1,2}'::int[]
.Zeilen mit übergeben
id IS NULL
keinen dieser Ausdrücke. UmNULL
Werte zusätzlich aufzunehmen:quelle
SELECT * from mytable where id in (1, 2, 3)
Dies bedeutet, dass immer dieselben Zeilen wie angezeigt werdenSELECT * from mytable where id = ANY('{1, 2, 3}')
, auch wenn sie möglicherweise unterschiedliche Abfragepläne haben.ANY
kann nicht mit dem!=
Bediener kombiniert werden. Ich denke nicht, dass es dokumentiert ist, aber esselect * from foo where id != ANY (ARRAY[1, 2])
ist nicht dasselbe wieselect * from foo where id NOT IN (1, 2)
. Funktioniert dagegenselect * from foo where NOT (id = ANY (ARRAY[1, 2]))
wie erwartet.ANY
kann mit dem!=
Operator kombiniert werden. Aber es steckt noch mehr dahinter. Ich habe oben ein Kapitel hinzugefügt. (Beachten Sie, dass dies<>
der Operator in Standard-SQL ist - obwohl dies!=
auch in Postgres akzeptiert wird.)NULL
Werte enthält ? WürdeWHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;
genauso gut funktionieren?(id = ...) IS NOT TRUE
funktioniert, weilid = ...
nur ausgewertet wird,TRUE
ob eine tatsächliche Übereinstimmung vorliegt . ErgebnisseFALSE
oderNULL
bestehen Sie unseren Test. Siehe: stackoverflow.com/a/23767625/939860 . Ihr hinzugefügter Ausdruck testet auf etwas anderes. Dies wäre gleichwertigWHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Es gibt zwei offensichtliche Punkte sowie die Punkte in der anderen Antwort:
Sie sind bei Verwendung von Unterabfragen genau gleichwertig:
Andererseits:
Nur der
IN
Operator erlaubt eine einfache Liste:Die Annahme, dass sie genau gleich sind, hat mich mehrmals überrascht, als ich vergaß, dass
ANY
dies mit Listen nicht funktioniert.quelle