配列にないPostgres


96

Postgresのネイティブ配列タイプを使用しており、IDが配列受信者IDにないレコードを検索しようとしています。

私は彼らがどこにいるのかを見つけることができます:

SELECT COUNT(*) FROM messages WHERE (3 = ANY (recipient_ids))

しかし、これはうまくいきません:

SELECT COUNT(*) FROM messages WHERE (3 != ANY (recipient_ids))
SELECT COUNT(*) FROM messages WHERE (3  = NOT ANY (recipient_ids))

この状態をテストする正しい方法は何ですか?


動作しWHERE 3 NOT IN recipient_idsますか?
Janus Troelsen、2012

1
関連注記:用としてtext[]int[]配列:select not(array[1,2,3] @> array[3]);
スティーブピーク

3
プロのヒント:null列が配列に含まれているかどうかを確認している場合、常に「いいえ」と表示されます。これは、nullが配列に含まれているかどうかをチェックすることができないという結論に来て、いくつか含む方法をデバッグの20分のように私を取った
アンドレ・ペーニャ

回答:



39

あなたはそれを少し変えて、「3はすべてのIDと同じではない」と言うことができます:

where 3 != all (recipient_ids)

良いマニュアルから:

9.21.4。ALL(配列)

expression operator ALL (array expression)

右側は括弧で囲まれた式であり、配列値を生成する必要があります。左側の式が評価され、指定された演算子を使用して配列の各要素と比較されます。これは、ブール結果を生成する必要があります。ALLすべての比較でtrueになる場合(配列の要素が0の場合を含む)の結果は "true"です。誤った結果が見つかった場合、結果は「偽」です。


これは実際anyにこのケースで機能しない理由を実際に説明していません
seanlinsley

これは理由を適切に説明しているので受け入れられるべきです。PSはあなたも見つけることができるanyall述べているpostgresのドキュメント、上:「x <> ANY (a,b,c) と等価ですx <> a OR <> b OR x <> c」。ref: postgresqltutorial.com/postgresql-any postgresqltutorial.com/postgresql-all
Tyler Temp

19

増強ALL/ANY回答

私は結果を使用する、allまたはany結果を達成するすべてのソリューションを好み、追加のメモ(たとえばNULLについて)を高く評価します。別の熟成として、これらはそれらの演算子について考える方法です。

あなたはそれらを短絡演算子と考えることができます:

  • all(array)配列内のすべての値を調べ、提供された演算子を使用してそれぞれを参照値と比較します。比較の結果がfalseになるとすぐに、プロセスはfalseで終了し、それ以外の場合はtrueになります。(短絡論理と同等and。)
  • any(array)配列内のすべての値を調べ、提供された演算子を使用してそれぞれを参照値と比較します。比較の結果がtrueになるとすぐに、プロセスはtrueで終了し、それ以外の場合はfalseで終了します。(短絡論理と同等or。)

これが3 <> any('{1,2,3}')望ましい結果をもたらさない理由です。プロセスは、3と1の不等式を比較します。これはtrueであり、すぐにtrueを返します。3以外の配列内の単一の値で、条件全体が真になります。最後の配列位置の3は確率です。使われたことがない。

3 <> all('{1,2,3}')一方、すべての値が等しくないことを確認ます。trueを生成するすべての比較から、falseを生成する要素(この場合は最後)まで実行し、全体的な結果としてfalseを返します。これはOPが望んでいることです。



11

アップデート:

postgres 9.3現在、

(contains演算子)NOTと併用してこれを実現することもできます。@>

IE。

SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];


11

NULLに注意する

両方ALL

(some_value != ALL(some_array))

そしてANY

NOT (some_value = ANY(some_array))

some_arraynullでない限り機能します。配列がnullの可能性がある場合は、coalesce()で説明する必要があります。

(some_value != ALL(coalesce(some_array, array[]::int[])))

または

NOT (some_value = ANY(coalesce(some_array, array[]::int[])))

ドキュメントから:

配列式がnull配列を生成する場合、ANYの結果はnullになります

配列式がnull配列を生成する場合、ALLの結果はnullになります


3

ANY / ALL演算子は配列インデックスでは機能しないことに注意してください。インデックスを考慮している場合:

SELECT COUNT(*) FROM "messages" WHERE 3 && recipient_ids

そしてネガティブ:

SELECT COUNT(*) FROM "messages" WHERE NOT (3 && recipient_ids)

その後、次のようにインデックスを作成できます。

CREATE INDEX recipient_ids_idx on tableName USING GIN(recipient_ids)

他の回答とは異なり、この回答は実際にはPostgreSQL配列オーバーラップ演算子を使用しています。&&
天井Gecko

6
これは、書いたとおりには機能しません。&&や@>などの配列演算子では、両方の要素が配列である必要がありますが、3はそうではありません。これを機能させるには、クエリを次のように記述する必要がありますSELECT COUNT(*) FROM "messages" WHERE ARRAY[3] && recipient_ids
Dologan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.