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))
この状態をテストする正しい方法は何ですか?
_SELECT COUNT(*) FROM "messages" WHERE NOT (3 = ANY (recipient_ids))
_
WHERE (condition)
を使用すると、WHERE NOT (condition)
をいつでも無効にできます。
それを少し変えて、「3はすべてのIDと等しくない」と言うことができます。
where 3 != all (recipient_ids)
ファインマニュアル から:
9.21.4。 ALL(配列)
expression operator ALL (array expression)
右側は括弧で囲まれた式であり、配列値を生成する必要があります。左側の式が評価され、指定されたoperatorを使用して配列の各要素と比較されます。ブール値の結果を生成する必要があります。
ALL
の結果は、すべての比較でtrueが得られた場合(配列にゼロ要素がある場合を含む)、 "true"です。偽の結果が見つかった場合、結果は「偽」です。
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が望んでいることです。
not (3 = any(recipient_ids))
?
アップデート:
postgres 9.3以降、
NOT
を_@>
_ (演算子を含む) と組み合わせて使用することもできます。
IE。
SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];
両方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になります
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)