Postgres配列に値が存在するかどうかを確認します


195

Postgres 9.0を使用して、特定の配列に値が存在するかどうかをテストする方法が必要です。これまでのところ、私はこのようなものを思いつきました:

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

しかし、これにはもっと簡単な方法があるはずだと私は考え続けています。これは良いようです:

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

私はそれで十分だと思います。ただし、他の方法がある場合は、共有してください!

回答:


322

構成を簡単にするANY

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

ANY(括弧の間の)右側のオペランドは、セット(サブクエリの結果など)または配列のいずれかです。使い方はいくつかあります:

重要な違い:(配列演算子<@@>&&。ら)を期待アレイオペランドとしてタイプの支持GINまたはのGiSTインデックスながら、PostgreSQLの標準分布でのANY構築が期待要素左オペランドとしてタイプし、これらのインデックスをサポートしていません。例:

これはNULL要素に対しては機能しません。をテストするにはNULL


ありがとう。マニュアルのその部分をスキップしたに違いありません。これはうまくいきます。自動キャストの副作用があります。例:SELECT 1 :: smallint = ANY( '{1,2,3}' :: int [])は機能します。ANY()を式の右側に配置するようにしてください。
マイクスタロフ

答えてくれてありがとう。私のクエリがローカルで機能するという問題が発生しましたが、herokuでこのメッセージがスローされていたためANY/ALL (array) requires array on right side、addを実行::int[]すると魅力的でした。
12:13のキンダフ

where S.employee_id <@ ANY( '"+ employeeIDsArray +"' :: int [])これはPSQLExceptionを返します:ERROR:missing dimension value
Ramprasad

3
これはインターネット時代の恐竜の質問ですが、私のような遅い人'something' = ANY(some_array)WHERE節でも使用できることを知っておく必要があります。Cromだけが知っている理由により、ここ4年間、配列コンパレーターをWHERE句で使用できないと考えていました。その時代はもう過ぎ去りました。(私は子供の頃頭に落ちました、それで私だけかもしれません)。
GT。

1
@GT .:その要点:どんな boolean表現このWHERE節で機能します-クロムは喜んでいます。
Erwin Brandstetter 2016

90

私が入り込んだトラップに注意してください:特定の値が配列に存在しないかどうかをチェックするときは、行うべきではありません:

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

でも使う

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

代わりに。


2
一種のダブルネガティブ。彼のALLvsの使用に注意してくださいANY
vol7ron 2013年

43
SELECT NOT value_variable = ANY('{1,2,3}'::int[])より読みやすいかもしれません
オンドレイBouda

28

他に方法がある場合は、共有してください。

2つの配列を比較できます。左の配列の値のいずれかが右の配列の値と重複する場合は、trueを返します。一種のハックですが、機能します。

SELECT '{1}'   && '{1,2,3}'::int[];  -- true
SELECT '{1,4}' && '{1,2,3}'::int[];  -- true
SELECT '{4}'   && '{1,2,3}'::int[];  -- false
  • 最初と2番目のクエリで1は、値は正しい配列にあります
  • true4が正しい配列に含まれていない場合でも、2番目のクエリはであることに注意してください。
  • 3番目のクエリの場合、左の配列(つまり4)の値は右の配列にないため、次のように返されますfalse

別のテーブルから列を検索して配列に値を含めるにはどうすればよいですか?たとえば、select * from beers where style_id in(select preferences from users where id = 1)limit 1; style_idは整数データ型です。プリファレンスはinteger []このエラーが発生しましたエラー:演算子が存在しません:integer = integer []行1:style_idが入っているビールから*を選択(selectプリファレンスf ... ^ヒント:指定された名前と引数タイプに一致する演算子はありません(s)明示的な型キャストを追加する必要がある場合があります
HP

@HPその質問を解決するにはさまざまな方法があります。新しい質問をする必要があります
vol7ron

既存の質問はありませんか?@ vol7ron
HP

@HPまったくありませんが、コメントは質問または回答に関するコメントです。通常は、情報を追加したり、対処されなかった情報を要求したりします。あなたはこの答えに関係のない質問をしています。コメントではなく、新しい投稿として質問することで、もっと幸運になると思います;)
vol7ron

@HP質問を投稿していない場合は、sqlfiddle.com /#!15 / 144cd / 3を実行して、必要な操作の例を確認してください。アレイのネストを解除する必要があるため、問題は異なります。
vol7ron

4

unnest同様に使用することができます。配列を行のセットに展開し、値が存在するかどうかを確認するのは、INまたはを使用するのと同じくらい簡単NOT INです。

例えば

  1. id => uuid

  2. exception_list_ids => uuid []

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


はい。私のクエリプランでは、SELECT UNNESTは= ANYほど良くないことに注意してください。クエリプランをチェックして、期待どおりの結果が得られるかどうかを確認することをお勧めします。
Rob Bygrave 2017年

3

配列内の要素の存在を探す場合、postgresのSQLパーサーを渡すために適切なキャストが必要です。次に、結合句で配列を含む演算子を使用したクエリの例を1つ示します。

簡単にするために、関連する部分のみをリストします。

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

示されているSQLの結合部分

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

以下も動作します

on t2.panel = ANY(t1.other_name)

列の正確なタイプを把握するために解析でテーブル定義をフェッチする必要がないため、追加のキャストが必要だと思います。他の人はこれについてコメントしてください。


0

こんにちは、私にとってはうまくいきます

select * from your_table where array_column :: text ilike ANY(ARRAY ['%text_to_search%' :: text]);

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.