4

私は2つのテーブルを持っています

表1

Column1
_______
   1
   2
   3
   4
   5
   6

表 2

Column 1
________
    4
 NULL    //This NULL value added after answering the question, to show the real problem
    5
    6
    7
    8
    9

これは一例です。やってみたところ、

SELECT column1 FROM Table1 WHERE column1 IN (SELECT column1 FROM Table2)

私は4,5,6を得ました

いつ

SELECT column1 FROM Table1 WHERE column1 NOT IN (SELECT column1 FROM Table2)

1,2,3 を取得できませんでしたが、 NULLです。

実際の場合、table1 の column1 は nvarchar(max) で、table2 の column1 は varchar(50) です。ただし、両方を varchar(50) にキャストしてみました。

4

3 に答える 3

8

IN具体的には、次のドキュメントを確認してください。

IN または NOT IN を使用してtest_expressionと比較されるサブクエリまたはによって返される null 値は、 UNKNOWN を返します。IN または NOT IN と一緒に null 値を使用すると、予期しない結果が生じる可能性があります。

あなたはそれらを示していませんが、あなたのデータには少なくとも 1 つの値が潜んでいると確信しています。NULL

NULL(s) を除外すると、NOT IN期待どおりに機能します。

SELECT column1 FROM Table1
WHERE column1 NOT IN (SELECT t2.column1 FROM Table2 t2
                      WHERE t2.column1 IS NOT NULL)

INNOT INは、手の波の中で正反対ですが、SQL の3 つの値を持つロジックを念頭に置く必要があります。形式INを使用して を書いたと想像してください

a IN (1,2,NULL)

これは次と同じように扱われます:

a = 1 OR a = 2 or a = NULL

a = 1 の行については、次のようになります。

TRUE OR TRUE OR UNKNOWN

ですTRUE。そして、a = 3 の任意の行については、次のようになります。

FALSE OR FALSE OR UNKNOWN

これはUNKNOWN

さて、NOT IN同じように考えてみましょう:

a NOT IN (1,2,NULL)

これは次と同じように扱われます:

a != 1 AND a != 2 AND a != NULL

a = 1 の行については、次のようになります。

FALSE AND TRUE AND UNKNOWN

ですFALSE。a = 3 の場合、次のようになります。

TRUE AND TRUE AND UNKNOWN

ですUNKNOWN。の存在は、この一連のs から値を生成するNULL方法がないことを意味します。ANDTRUE

于 2013-09-18T06:25:20.377 に答える
6

nullこれは、Table2に値がある場合に発生する可能性があります。代わりに次のクエリを使用してください。

select *
from Table1 as t1
where not exists (select * from Table2 as t2 where t2.column1 = t1.column1);

sql fiddle demo

テスト クエリ:

-- Table2 doesn't have null values, works good
SELECT column1 FROM Table1 WHERE column1 IN (SELECT column1 FROM Table2);
SELECT column1 FROM Table1 WHERE column1 NOT IN (SELECT column1 FROM Table2);

insert into Table2
select null;

-- nothing returned by query, because of null values in Table2
SELECT column1 FROM Table1 WHERE column1 NOT IN (SELECT column1 FROM Table2);

-- works good
select *
from Table1 as t1
where not exists (select * from Table2 as t2 where t2.column1 = t1.column1);

これは、SQL の3 値ロジックが原因で発生します。 Damien_The_Unbeliever のわかりやすい説明を参照してください。not null次のようにクエリを使用できます。

SELECT column1 FROM Table1 WHERE column1 NOT IN (SELECT column1 FROM Table2 where column1 is not null);

existsしかし、それは null を暗黙的に (単に を使用しているという理由だけで) 除外するので、私はもっと好き=です。

さらに、クエリのようなクエリをエイリアスなしで質問に使用しないでください (実際にはエイリアスではなく、Table.columnまたはのようなドット表記)。誤った結果Alias.columnが得られる可能性があるためです。列には常にドット表記を使用してください。したがって、クエリは次のようになります。

SELECT t1.column1 FROM Table1 as t1 WHERE t1.column1 NOT IN (SELECT t2.column1 FROM Table2 as t2 where t2.column1 is not null);
于 2013-09-18T06:26:46.770 に答える
3

これが、NOT IN を避けるべき主な理由です。YES/NO/UNKNOWN の 3 方向のロジックに基づいています :-)

col IN (1,2,NULL) 
is the logically equivalent to 
col=1 OR col=2 OR col=NULL 

col NOT IN (1,2,NULL) 
is the logically equivalent to
col<>1 AND col<>2 AND col<>NULL 

現在、NULL との比較は UNKNOWN と評価され、"col IS (NOT) NULL" のみが正しいです。

OR 条件を取得した場合、UNKNOWN は問題ではありませんが、AND 条件で UNKNOWN が 1 つあると、最終的な UNKNOWN になります。

外側の table1 に NULL を追加し、table2 から NULL を削除すると、IN/NOT IN の両方の回答セットでこの行が欠落していることに気付くでしょう。

最良の回避策は、代わりに EXISTS/NOT EXISTS を使用することです。UNKNOWN と評価される条件は無視され、単純に FALSE として扱われるため、YES/NO しかありません。

于 2013-09-18T06:44:28.280 に答える