Überprüfen Sie, ob der Wert im Postgres-Array vorhanden ist

193

Mit Postgres 9.0 muss ich testen können, ob in einem bestimmten Array ein Wert vorhanden ist. Bisher habe ich mir so etwas ausgedacht:

select '{1,2,3}'::int[] @> (ARRAY[]::int[] || value_variable::int)

Aber ich denke immer wieder, dass es einen einfacheren Weg geben sollte, ich kann es einfach nicht sehen. Das scheint besser zu sein:

select '{1,2,3}'::int[] @> ARRAY[value_variable::int]

Ich glaube, es wird ausreichen. Aber wenn Sie andere Möglichkeiten haben, teilen Sie dies bitte mit!

Mike Starov
quelle

Antworten:

321

Einfacher mit dem ANYKonstrukt:

SELECT value_variable = ANY ('{1,2,3}'::int[])

Der rechte Operand von ANY(zwischen Klammern) kann entweder eine Menge (z. B. Ergebnis einer Unterabfrage) oder ein Array sein . Es gibt verschiedene Möglichkeiten, es zu verwenden:

Wichtige Unterschiede: (Array Operatoren <@, @>, &&. Et al) erwarten Array - Typen als Operanden und Unterstützung GIN oder GiST Indizes in der Standardverteilung von PostgreSQL, während das ANYKonstrukt erwartet eine Elementtyp wie linken Operanden und unterstützt nicht diese Indizes. Beispiel:

Nichts davon funktioniert für NULLElemente. So testen Sie NULL:

Erwin Brandstetter
quelle
Vielen Dank. Muss diesen Teil des Handbuchs übersprungen haben. Das funktioniert super. Es hat einen Nebeneffekt des automatischen Gießens. Beispiel: SELECT 1 :: smallint = ANY ('{1,2,3}' :: int []) funktioniert. Stellen Sie einfach sicher, dass ANY () auf der rechten Seite des Ausdrucks steht.
Mike Starov
Danke für die Antwort. Haben Sie ein Problem , wo meine Abfrage auf lokale gearbeitet, aber in Heroku Diese Nachricht wurde werfen ANY/ALL (array) requires array on right side, das Add von ::int[]tat der Reiz.
Kinduff
where S.employee_id <@ ANY ('"+ employeeIDsArray +"' :: int []) Dies gibt PSQLException zurück: ERROR: fehlender Dimensionswert
Ramprasad
3
Obwohl dies in Internetjahren eine Dinosaurierfrage ist, sollten langsame Leute wie ich darauf aufmerksam gemacht werden, dass 'something' = ANY(some_array)sie auch in einer WHEREKlausel verwendet werden können. Aus Gründen, die nur Crom bekannt sind, habe ich in den letzten vier Jahren gedacht, dass ich in WHEREKlauseln keine Array-Komparatoren verwenden könnte . Diese Zeiten sind jetzt vorbei. (Ich wurde als Kind auf den Kopf fallen gelassen, also bin ich es vielleicht nur).
GT.
1
@GT.: Das Wesentliche: Jeder boolean Ausdruck funktioniert in der WHEREKlausel - Crom will.
Erwin Brandstetter
90

Achten Sie auf die Falle, in die ich geraten bin: Wenn Sie überprüfen, ob ein bestimmter Wert in einem Array nicht vorhanden ist, sollten Sie Folgendes nicht tun:

SELECT value_variable != ANY('{1,2,3}'::int[])

aber verwenden

SELECT value_variable != ALL('{1,2,3}'::int[])

stattdessen.

Murison
quelle
2
Eine Art doppeltes Negativ; ALLANY
Beachten Sie
43
SELECT NOT value_variable = ANY('{1,2,3}'::int[])könnte besser lesbar sein
Ondřej Bouda
28

Wenn Sie jedoch andere Möglichkeiten haben, teilen Sie diese bitte mit.

Sie können zwei Arrays vergleichen. Wenn sich einer der Werte im linken Array mit den Werten im rechten Array überschneidet, wird true zurückgegeben. Es ist irgendwie hackisch, aber es funktioniert.

SELECT '{1}'   && '{1,2,3}'::int[];  -- true
SELECT '{1,4}' && '{1,2,3}'::int[];  -- true
SELECT '{4}'   && '{1,2,3}'::int[];  -- false
  • In der ersten und zweiten Abfrage befindet sich der Wert 1im richtigen Array
  • Beachten Sie, dass die zweite Abfrage lautet true, obwohl der Wert 4nicht im richtigen Array enthalten ist
  • Bei der dritten Abfrage befinden sich keine Werte im linken Array (dh 4) im rechten Array, daher wird zurückgegebenfalse
vol7ron
quelle
Wie kann ich nach einer Spalte aus einer anderen Tabelle suchen, um einen Wert im Array zu haben? zB * aus Bieren auswählen, bei denen style_id in (Einstellungen von Benutzern auswählen, bei denen id = 1 ist) 1 begrenzen; style_id ist ein ganzzahliger Datentyp. Einstellungen ist Ganzzahl [] Ich erhalte diesen Fehler FEHLER: Operator existiert nicht: Ganzzahl = Ganzzahl [] Zeile 1: Wählen Sie * aus Bieren aus, in denen style_id in (Einstellungen auswählen f ... ^ TIPP: Kein Operator stimmt mit dem angegebenen Namen und Argumenttyp überein (s). Möglicherweise müssen Sie explizite Typumwandlungen hinzufügen.
HP
@ HP Es gibt verschiedene Möglichkeiten, um diese Frage zu lösen, sollten Sie eine neue Frage stellen
vol7ron
Sind Sie sicher, dass es keine Frage gibt? @ vol7ron
HP
@HP Überhaupt nicht, aber Kommentare sind für Kommentare zu einer Frage oder Antwort; In der Regel, um weitere Informationen hinzuzufügen oder weitere Informationen anzufordern, die nicht adressiert wurden. Sie stellen eine Frage, die nicht mit dieser Antwort zusammenhängt. Ich denke, Sie werden mehr Glück haben, wenn Sie Ihre Frage als neuen Beitrag stellen, nicht im Kommentar;)
vol7ron
@HP Wenn Sie Ihre Frage nicht gestellt haben, finden Sie hier: sqlfiddle.com/#!15/144cd/3 Ein Beispiel dafür, was Sie tun müssen - Ihr Problem ist anders, weil Sie Ihr Array entstören müssen.
Vol7ron
4

unnestkann auch verwendet werden. Es erweitert das Array auf eine Reihe von Zeilen und die einfache Überprüfung, ob ein Wert vorhanden ist oder nicht, ist so einfach wie die Verwendung von INoder NOT IN.

z.B

  1. id => uuid

  2. exception_list_ids => uuid []

select * from table where id NOT IN (select unnest(exception_list_ids) from table2)

pg2286
quelle
Ja. Beachten Sie, dass SELECT UNNEST in meinen Abfrageplänen nicht so gut ist wie = ANY. Ich würde empfehlen, die Abfragepläne zu überprüfen, um festzustellen, ob Sie das bekommen, was Sie wollen / erwarten.
Rob Bygrave
3

Wenn Sie nach dem Vorhandensein eines Elements in einem Array suchen, ist eine ordnungsgemäße Umwandlung erforderlich, um den SQL-Parser von postgres zu übergeben. Hier ist eine Beispielabfrage mit Array enthält Operator in der Join-Klausel:

Der Einfachheit halber liste ich nur den relevanten Teil auf:

table1 other_name text[]; -- is an array of text

Der Join-Teil von SQL wird angezeigt

from table1 t1 join table2 t2 on t1.other_name::text[] @> ARRAY[t2.panel::text]

Das Folgende funktioniert auch

on t2.panel = ANY(t1.other_name)

Ich vermute nur, dass das zusätzliche Casting erforderlich ist, da die Analyse die Tabellendefinition nicht abrufen muss, um den genauen Typ der Spalte zu ermitteln. Andere kommentieren dies bitte.

Kemin Zhou
quelle
0

Hallo, das funktioniert gut für mich, vielleicht nützlich für jemanden

Wählen Sie * aus Ihrer_Tabelle aus, wobei array_column :: text wie ANY (ARRAY ['% text_to_search%' :: text]);

Dave Kraczo
quelle