web-dev-qa-db-ja.com

配列にないPostgres

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))

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

73
user577808
_SELECT COUNT(*) FROM "messages" WHERE NOT (3 = ANY (recipient_ids))
_

WHERE (condition)を使用すると、WHERE NOT (condition)をいつでも無効にできます。

104
Frank Farmer

それを少し変えて、「3はすべてのIDと等しくない」と言うことができます。

where 3 != all (recipient_ids)

ファインマニュアル から:

9.21.4。 ALL(配列)

expression operator ALL (array expression)

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

35
mu is too short

_ALL/ANY_回答の増強

結果を達成するためにallまたはanyを使用するすべてのソリューションを好み、追加のメモを評価します(例[〜#〜] null [〜#〜] s )。別の拡張として、これらの演算子について考える方法があります。

それらをショートサーキット演算子と考えることができます:

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

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

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

11
ThomasH

not (3 = any(recipient_ids))

9

アップデート:

postgres 9.3以降、

NOTを_@>_ (演算子を含む) と組み合わせて使用​​することもできます。

IE。

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

7
Rooster

NULLに注意してください

両方ALL

(some_value != ALL(some_array))

ANY

NOT (some_value = ANY(some_array))

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

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

または

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

docs から:

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

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

6
isapir

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)
3
jamming james