Postgres: controleren of het matrixveld waarde bevat?

Ik weet zeker dat dit een dubbele vraag is in de zin dat het antwoord ergens te vinden is, maar ik heb het antwoord na 10 minuten Googlen niet kunnen vinden, dus ik zou een beroep doen op de redactie om dat niet te doen sluit het op basis van het feit dat het misschien nuttig is voor andere mensen.

Ik gebruik Postgres 9.5. Dit is mijn tafel:

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

Ik wil alle rijen vinden met “Journaal” in pub_types.

Ik heb de documenten gevonden en gegoogled en dit is wat ik heb geprobeerd:

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";

Ik heb de postgres array-documentengescand, maar kan het niet zie een eenvoudig voorbeeld van het uitvoeren van een query, en StackOverflow-vragen lijken allemaal gebaseerd te zijn op meer gecompliceerde voorbeelden.


Antwoord 1, autoriteit 100%

Dit zou moeten werken:

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

d.w.z. de syntaxis is <value> = ANY ( <array> ). Merk ook op dat letterlijke tekenreeksen in postresql worden geschreven met enkele aanhalingstekens.


Antwoord 2, autoriteit 40%

Met de operator ANYkunt u slechts op één waarde zoeken.

Bijvoorbeeld

SELECT * FROM mytable WHERE 'Book' = ANY(pub_types);

Als u op meerdere waarden wilt zoeken, kunt u de operator @>gebruiken.

Bijvoorbeeld

SELECT * FROM mytable WHERE pub_types @> '{"Journal", "Book"}';

U kunt aangeven in welke volgorde u maar wilt.


Antwoord 3, autoriteit 3%

Hoewel misschien niet de meest efficiënte aanpak, werkte dit voor mij:

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

Het gebruik van de bevat-operator @>(zie het antwoord van Sudharsan Thumatti hierboven) is waarschijnlijk een betere keuze omdat het een B-Tree-vergelijkingsfunctie gebruikt per PostgreSQL-documenten.

Afhankelijk van uw normalisatiebehoeften, is het misschien beter om een ​​aparte tabel met een FK-referentie te implementeren, omdat u mogelijk betere prestaties en beheersbaarheid krijgt.


Antwoord 4, autoriteit 2%

In plaats van INkunnen we ANYgebruiken met arrays die zijn gegoten om array op te sommen, bijvoorbeeld:

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[]);

Of we kunnen nog steeds de ‘IN’-clausule gebruiken, maar eerst moeten we deze ‘unnesten’:

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

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

Other episodes