web-dev-qa-db-ja.com

NULLまたはIS NULLのIN句

Postgresはデータベースです

IN句にNULL値を使用できますか?例:

SELECT *
FROM tbl_name
WHERE id_field IN ('value1', 'value2', 'value3', NULL)

これら4つの値に制限したいと思います。

上記のステートメントを試してみましたが、機能しません。うまく実行されますが、id_fieldsがNULLのレコードは追加されません。

また、OR条件を追加しようとしましたが、これによりクエリが実行され、最後まで見えなくなります。

SELECT *
FROM tbl_name
WHERE other_condition = bar
AND another_condition = foo
AND id_field IN ('value1', 'value2', 'value3')
OR id_field IS NULL

助言がありますか?

68
Phill Pafford

inステートメントは、field=val1 or field=val2 or field=val3と同じように解析されます。そこにヌルを入れると、field=nullになりますが、動作しません。

コメント by Marc B

私は明快さのためにこれをします

SELECT *
FROM tbl_name
WHERE 
(id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)
93
Daniel A. White

operator precedence が原因でクエリは失敗します。 ANDORの前にバインドします!
一対の括弧が必要です。これは「明確さ」の問題ではなく、純粋な論理的必要性です。

SELECT *
FROM   tbl_name
WHERE  other_condition = bar
AND    another_condition = foo
AND   (id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)

追加された括弧は、ANDの前のORバインディングを防ぎます。他のWHERE条件がない(ANDがない)場合、括弧はneedしません。受け入れられた答えは、この点で少し誤解を招きます。

18
SELECT *
FROM tbl_name
WHERE coalesce(id_field,'unik_null_value') 
IN ('value1', 'value2', 'value3', 'unik_null_value')

そのため、チェックからヌルを除去します。 id_fieldにnull値が与えられた場合、合体関数はnullの代わりに 'unik_null_value'を返し、IN-listに 'unik_null_valueを追加すると、クエリはid_fieldがvalue1-3またはnullの投稿を返します。

8
Ove Halseth

ダニエルが答えた質問は、完全に問題ありません。 NULLに関するメモを残したかった。列にNULL値が含まれる場合は、NOT IN演算子の使用に注意する必要があります。列にNULL値が含まれていて、NOT IN演算子を使用している場合、出力は得られません。これは、ここで説明されている方法です http://www.oraclebin.com/2013/01/beware-of-nulls.html 、私が出会って共有したいと思った非常に良い記事です。

7
Sushant Butta

注:外部リンクが死んでいると誰かが主張したのでSushant Butta's answer私は別の回答としてここにコンテンツを投稿しました。

[〜#〜] nulls [〜#〜]に注意してください。

今日、INおよびNOT IN演算子を使用しているときに、クエリの非常に奇妙な動作に遭遇しました。実際、2つのテーブルを比較して、table bの値がtable aに存在するかどうかを調べ、列にnullの値が含まれている場合の動作を調べたいと思いました。そのため、この動作をテストするための環境を作成しました。

テーブルtable_aを作成します。

SQL> create table table_a ( a number);
Table created.

テーブルtable_bを作成します。

SQL> create table table_b ( b number);
Table created.

いくつかの値をtable_aに挿入します。

SQL> insert into table_a values (1);
1 row created.

SQL> insert into table_a values (2);
1 row created.

SQL> insert into table_a values (3);
1 row created.

いくつかの値をtable_bに挿入します。

SQL> insert into table_b values(4);
1 row created.

SQL> insert into table_b values(3);
1 row created.

ここで、IN演算子を使用してtable_aから値をチェックすることにより、table_bの値の存在をチェックするクエリを実行します。

SQL> select * from table_a where a in (select * from table_b);
         A
----------
         3

以下のクエリを実行して、存在しないことを確認します。

SQL> select * from table_a where a not in (select * from table_b);
         A
----------
         1
         2

出力は予想通りでした。テーブルtable_bnull値を挿入し、上記の2つのクエリの動作を確認します。

SQL> insert into table_b values(null);
1 row created.

SQL> select * from table_a where a in (select * from table_b);
         A
----------
         3

SQL> select * from table_a where a not in (select * from table_b);

no rows selected

最初のクエリは期待どおりに動作しましたが、2番目のクエリはどうなりましたか?なぜ出力が得られなかったのですか?クエリに違いはありますか? いいえ

変更はテーブルtable_bのデータにあります。テーブルにnull値を導入しました。しかし、なぜこのように動作するのでしょうか? 2つのクエリを"AND"および"OR"演算子に分割しましょう。

最初のクエリ:

最初のクエリは、このように内部的に処理されます。したがって、最初の2つのオペランドがnullまたはtrueに評価されるため、falseが問題になることはありません。しかし、私の第3オペランドa = nullは、trueにもfalseにも評価されません。 nullのみに評価されます。

select * from table_a whara a = 3 or a = 4 or a = null;

a = 3  is either true or false
a = 4  is either true or false
a = null is null

2番目のクエリ:

2番目のクエリは次のように処理されます。 "AND"演算子を使用しているため、どのオペランドでもtrue以外のものは出力されません。

select * from table_a whara a <> 3 and a <> 4 and a <> null;

a <> 3 is either true or false
a <> 4 is either true or false
a <> null is null

では、これをどのように処理しますか? not null演算子を使用しながら、テーブルtable_bからすべてのNOT IN値を選択します。

SQL> select * from table_a where a not in (select * from table_b where b is not null);

         A
----------
         1
         2

したがって、NOT IN演算子を使用するときは、列のNULL値に常に注意してください。

NULL !!に注意してください

3
1000111

私はそれが答えるのが遅いことを知っていますが、他の誰かにとっては有用かもしれませんあなたはサブクエリを使用してnullを0に変換できます

SELECT *
FROM (SELECT CASE WHEN id_field IS NULL 
                THEN 0 
                ELSE id_field 
            END AS id_field
      FROM tbl_name) AS tbl
WHERE tbl.id_field IN ('value1', 'value2', 'value3', 0)
0
ch2o