it-swarm.com.de

PostgreSQL LIKE-Abfrage im ARRAY-Feld

Gibt es eine Möglichkeit, eine Postgres LIKE-Abfrage in einem ARRAY-Feld durchzuführen?

Derzeit möchte ich so etwas:

SELECT * FROM list WHERE lower(array_field) LIKE '1234%'

Derzeit wird nicht so viel niedriger benötigt. Es sollte jedoch EIN passendes Feld im ARRAY finden. Ist das überhaupt möglich?

Derzeit verwende ich eine materialisierte Ansicht, um die "List" -Tabelle mit einem JOIN und einem ARRAY_AGG() zu generieren, da ich einer Tabelle beitrete, in der sich möglicherweise mehr Werte in der richtigen Tabelle befinden. Welches würde Felder in der linken Tabelle duplizieren, was nicht das ist, was ich will.

Bearbeiten Sie so, wie ich die Ansicht erstelle (wirklich träge und hässlich):

CREATE MATERIALIZED VIEW article_list_new AS
SELECT a.id, 
       a.oa_nr, 
       a.date_deleted, 
       a.lock, 
       a.sds_nr, 
       a.kd_art_nr, 
       a.kd_art_index, 
       a.kd_art_extend, 
       a.surface, 
       a.execution, 
       a.surface_area, 
       a.cu_thickness, 
       a.endintensity, 
       a.drilling, 
       array_agg(o.id::text) AS offer_list 
FROM article_list a LEFT JOIN task_offer o ON o.article = a.oa_nr 
GROUP BY .....;  

Ich muss auch die IDs der Tabelle task_offer Zurückgeben.

7

Sie können unnest() wie bereits erwähntes @dezso verwenden, beispielsweise mit einem LATERAL-Join (Postgres 9.3+).

SELECT l.*
FROM   list l, unnest(array_field) a  -- implicit lateral
WHERE  lower(a) LIKE '1234%';

Für den vorliegenden Fall benötigen Sie nichts davon. Überhaupt keine materialisierte Ansicht. Diese Abfrage für die zugrunde liegenden Tabellen ist schneller, da ein Index verwendet werden kann:

SELECT *  -- or selected columns
FROM   article_list a
JOIN   LATERAL  (                      -- only matching IDs
   SELECT array_agg(id) AS offer_list
   FROM   task_offer
   WHERE  article = a.oa_nr            -- LATERAL reference  
   AND    id::text ILIKE '1234%'       -- or just LIKE
   ) o ON offer_list IS NOT NULL;

offer_list Ist ein Array des ursprünglichen Datentyps in meinem Ergebnis und enthält nur übereinstimmende IDs.

Gibt eine einzelne Zeile aus article_list Mit einem Array übereinstimmender IDs in task_offer Zurück. Fügen Sie einen text_pattern_ops - Index (für links verankerte Übereinstimmungen) hinzu, um die beste Leseleistung zu erzielen:

CREATE INDEX task_offer_foo_idx ON task_offer (article, (id::text) text_pattern_ops);

Oder ein Trigrammindex für Infix-Übereinstimmungen (nicht links verankert):

Oder vielleicht eine einfache Verbindung für selektive Muster:

SELECT a.*, o.offer_list -- or selected columns
FROM   article_list a
JOIN   (                          -- only matching IDs
   SELECT article, array_agg(id) AS offer_list
   FROM   task_offer
   WHERE  id::text ILIKE '1234%'  -- or just LIKE
   GROUP  BY 1
   ) o ON o.article = a.oa_nr;

Benötigt auch einen Index für article_list. (Was Sie wahrscheinlich haben - keine Informationen in der Frage.) Wie:

CREATE INDEX article_list_oa_nr_idx ON article_list (oa_nr);
9

Haben Sie die parray_gin-Erweiterung in Betracht gezogen, die sich ebenfalls hier befindet?

Ich habe es noch nicht in der Produktion verwendet, aber nach allem, was ich davon gesehen habe, macht es das, was Sie wollen, gegen das Array. Sie können den relevanten Index in der materialisierten Ansicht erstellen.

Ich würde das jedoch nur tun, wenn Sie die materialisierte Ansicht trotzdem haben würden. Ansonsten denke ich, dass die Antwort von @ ErwinBrandstetter besser ist, als eine materialisierte Ansicht zu erstellen, die nur den Index enthält.

4
jjanes