web-dev-qa-db-ja.com

ARRAYフィールドのPostgreSQL LIKEクエリ

ARRAYフィールドでPostgres LIKEクエリを実行する方法はありますか?

現在私はそのようなものが欲しい:

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

現在はそれほど必要ありません。ただし、ARRAY内で一致するフィールドが1つ検出されます。それは可能ですか?

現在、マテリアライズドビューを使用して、JOINとARRAY_AGG()を使用して「リスト」テーブルを生成しています。左側のテーブルのフィールドを複製するのは、私が望むものではありません。

これを編集して、ビューを作成する方法を説明します(実際には緩慢で醜い)。

_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 .....;  
_

_task_offer_テーブルのIDも返す必要があります。

7

unnest()は、すでに述べた@dezsoのように、たとえばLATERAL結合で使用できます(Postgres 9.3以降)。

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

提示されたケースでは、これは必要ありません。マテリアライズドビューはまったくありません。インデックスを使用できるため、基になるテーブルに対するこのクエリはより高速です。

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は、結果の元のデータ型の配列で、only一致するIDが含まれています。

戻り値単一article_listからの行とtask_offer内の一致するIDの配列。 text_pattern_opsインデックス(左アンカー一致の場合)を追加して、最高の読み取りパフォーマンスを取得します。

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

または、インフィックス一致のトライグラムインデックス(左アンカーされていない):

あるいは、選択的なパターンの単純な結合:

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;

article_listのインデックスも必要です。 (おそらくあなたが持っているもの-質問には情報がありません。)のように:

CREATE INDEX article_list_oa_nr_idx ON article_list (oa_nr);
9

parray_gin extension も検討しましたか? here にもありますか?

私はまだそれを本番環境で使用していませんが、私がそれを見てきたことから、それはあなたがアレイに対して望むことを行います。マテリアライズドビューに関連するインデックスを作成できます。

ただし、とにかくマテリアライズドビューを使用する場合にのみ、これを行います。それ以外の場合、@ ErwinBrandstetterの答えは、インデックスを保持するためだけにマテリアライズドビューを作成するよりも優れていると思います。

4
jjanes