Postgres: Überprüfen Sie, ob das Array-Feld einen Wert enthält.

78

Ich bin mir sicher, dass dies eine doppelte Frage in dem Sinne ist, dass die Antwort irgendwo da draußen ist, aber ich konnte die Antwort nach 10 Minuten Googeln nicht finden, daher appelliere ich an die Redakteure, sie nicht zu schließen die Grundlage, dass es für andere Menschen nützlich sein könnte.

Ich benutze Postgres 9.5. Das ist mein Tisch:

        Column          │           Type            │                                Modifiers
─────────────────────────┼───────────────────────────┼─────────────────────────────────────────────────────────────────────────
 id                      │ integer                   │ not null default nextval('mytable_id_seq'::regclass)
 pmid                    │ character varying(200)    │
 pub_types               │ character varying(2000)[] │ not null

Ich möchte alle Zeilen mit "Journal" in finden pub_types.

Ich habe die Dokumente gefunden und gegoogelt und Folgendes habe ich versucht:

select * from mytable where ("Journal") IN pub_types;
select * from mytable where "Journal" IN pub_types;
select * from mytable where pub_types=ANY("Journal");
select * from mytable where pub_types IN ("Journal");
select * from mytable where where pub_types contains "Journal";

Ich habe die Postgres-Array-Dokumente gescannt , kann jedoch kein einfaches Beispiel für die Ausführung einer Abfrage sehen, und StackOverflow-Fragen scheinen alle auf komplizierteren Beispielen zu beruhen.

Richard
quelle

Antworten:

136

Das sollte funktionieren:

select * from mytable where 'Journal'=ANY(pub_types);

dh die Syntax ist <value> = ANY ( <array> ). Beachten Sie auch, dass Zeichenfolgenliterale in postresql in einfache Anführungszeichen geschrieben werden.

Redneb
quelle
Vielen Dank!
Richard
@redneb Wie wäre es, wenn ich überprüfen möchte, ob das Array-Feld ein Element in einem Array enthält?
Aaron
Ich bekommeERROR: input of anonymous composite types is not implemented
Shane
Ist das dasselbe wie <value> IN ( <array> )?
jallen0927
2
Was ist mit dieser Syntax bezüglich der Leistung? Wählen Sie * aus mytable, wobei pub_types @> array ['Journal' :: text];
Nina
43

Mit JEDEM Operator können Sie nur nach einem Wert suchen.

Zum Beispiel,

select * from mytable where 'Book' = ANY(pub_types);

Wenn Sie mehrere Werte suchen möchten, können Sie den Operator @> verwenden .

Zum Beispiel,

select * from mytable where pub_types @> '{"Journal", "Book"}';

Sie können angeben, in welcher Reihenfolge Sie möchten.

Sudharsan Thumatti
quelle
22
@>means enthält alle Werte in diesem Array. Wenn Sie suchen möchten, ob das aktuelle Array Werte in einem anderen Array enthält, können Sie verwenden &&. select * from mytable where pub_types && '{"Journal", "Book"}';
jallen0927
1
Ich weiß nicht, ob es sich um eine Version handelt, aber sowohl @> als auch && haben bei Postgres 9.6 genau gleich funktioniert. Beide stimmten mit jedem Element in der Liste überein. Nur dass @> auch mit einer leeren Liste '{}' übereinstimmte.
Marcelus Trojahn
6

Das hat bei mir funktioniert:

select * from mytable
where array_to_string(pub_types, ',') like '%Journal%'

Abhängig von Ihren Normalisierungsanforderungen ist es möglicherweise besser, eine separate Tabelle mit einer FK-Referenz zu implementieren, da Sie möglicherweise eine bessere Leistung und Verwaltbarkeit erzielen.

Shane
quelle
Wie Tags, wenn Sie nicht vorhaben, eine Tabelle mit Tags zu führen oder nur eine einzige Entität zu haben, die sie verwendet.
Barnacle.m
1
Dies wird zu falsch positiven
Ergebnissen führen,
1
Die Art und Weise, wie der OP die Frage formulierte, scheint, als wollte er Journal irgendwo in der Zeichenfolge finden. Wenn Sie nur dort übereinstimmen möchten, wo es sich speziell um das Wort Journal handelt, entfernen Sie einfach die führenden und nachfolgenden Platzhalterzeichen (dh%).
Shane
1
Nizza - hat es mir ermöglicht, eine ILIKE-Abfrage über ein Array durchzuführen. Vielen Dank! SELECT * FROM archive WHERE ARRAY_TO_STRING(kw, ',') ILIKE '%pLASt%';
Victoria Stuart
2

Anstelle von können INwir ANYArrays verwenden, die in Enum-Arrays umgewandelt wurden, zum Beispiel:

create type example_enum as enum (
  'ENUM1', 'ENUM2'
);

create table example_table (
  id integer,
  enum_field example_enum
);

select 
  * 
from 
  example_table t
where
  t.enum_field = any(array['ENUM1', 'ENUM2']::example_enum[]);

Oder wir können immer noch die 'IN'-Klausel verwenden, aber zuerst sollten wir sie' unnest 'machen:

select 
  * 
from 
  example_table t
where
  t.enum_field in (select unnest(array['ENUM1', 'ENUM2']::example_enum[]));

Beispiel: https://www.db-fiddle.com/f/LaUNi42HVuL2WufxQyEiC/0

Cepr0
quelle
-1

Das hat bei mir funktioniert

let exampleArray = [1, 2, 3, 4, 5];
let exampleToString = exampleArray.toString(); //convert to toString
let query = `Select * from table_name where column_name in (${exampleToString})`; //Execute the query to get response

Ich habe das gleiche Problem, dann habe ich nach einer Stunde Mühe erfahren, dass in der Abfrage nicht direkt auf das Array zugegriffen werden sollte. Also fand ich dann heraus, dass die Daten in der Klammer selbst gesendet werden sollten, dann habe ich dieses Array wieder in einen String mit der toString-Methode in js konvertiert. Ich habe also die obige Abfrage ausgeführt und mein erwartetes Ergebnis erhalten

Srikanth
quelle
4
Bitte fügen Sie dem Code immer eine Erklärung hinzu. Dies verbessert Ihre Antwortqualität.
DaFois