1

join と in および exists 句の違いを説明する記事を読んでいましたが、NOT IN と NOT EXISTS 句を使用した場合の異なる結果の説明に混乱しました。NOT EXISTS 句と NOT IN 句の出力に違いがある理由を誰かが明確にすることはできますか? テーブル t2 から NULL 行 (t2.id = 8) を削除した後に試してみましたが、それでも同じ結果が得られました。

記事の SQL スクリプトは次のとおりです。

CREATE TABLE t1 (id INT, title VARCHAR(20), someIntCol INT)
GO
CREATE TABLE t2 (id INT, t1Id INT, someData VARCHAR(20))
GO

INSERT INTO t1
SELECT 1, 'title 1', 5 UNION ALL
SELECT 2, 'title 2', 5 UNION ALL
SELECT 3, 'title 3', 5 UNION ALL
SELECT 4, 'title 4', 5 UNION ALL
SELECT null, 'title 5', 5 UNION ALL
SELECT null, 'title 6', 5

INSERT INTO t2
SELECT 1, 1, 'data 1' UNION ALL
SELECT 2, 1, 'data 2' UNION ALL
SELECT 3, 2, 'data 3' UNION ALL
SELECT 4, 3, 'data 4' UNION ALL
SELECT 5, 3, 'data 5' UNION ALL
SELECT 6, 3, 'data 6' UNION ALL
SELECT 7, 4, 'data 7' UNION ALL
SELECT 8, null, 'data 8' UNION ALL
SELECT 9, 6, 'data 9' UNION ALL
SELECT 10, 6, 'data 10' UNION ALL
SELECT 11, 8, 'data 11'

SQL クエリとその説明は次のとおりです。

-- IN で正しい結果が得られません。-- これは、IN が NULL と 3 値ロジックを処理する方法によるものです -- NULL は不明として扱われるため、t2.t1id に null がある場合 -- NOT IN は NOT TRUE または NOT UNKNOWN を返します。そして、どちらも真ではありません。-- t2 テーブルの t1id 列に NULL がある場合、NOT IN クエリは常に空のセットを返します。

SELECT    t1.* 
FROM    t1 
WHERE    t1.id NOT IN (SELECT t1id FROM t2)

-- NOT EXISTS は正しい結果を取得します

SELECT    t1.* 
FROM    t1 
WHERE    NOT EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id)
GO

DROP TABLE t2
DROP TABLE t1

記事へのリンクは次のとおりです。 http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210.aspx

ありがとうございました!

4

1 に答える 1

0

ご覧のとおり、多くの場合同じものとして使用できますが、その背後にある詳細を忘れることはできません。

との両方を適用しても同じ結果がNOT INNOT EXISTSられる可能性がありますが、値に関係するクエリに違いがあることがわかりNULLます。値NOT EXISTSを持つ行を取得する唯一の方法だからです。NULL

次の例でよくわかります。

update cars set c_owner = NULL where c_id = BMW03444

うーん…まだ売れていない車の在庫がないか見てみましょう。

select count(*) from cars where c_owner not it (select c_name from customers);

出力:

カウント(*): 0

どこが失敗?とてもシンプルです。購入者がリストに含まれていない車のグループをリクエストしているのではありません。所有者のいない車を求めているだけです。リストに載っていなくても、誰でも。正しい形式は次のとおりです。

select count(*) 
from cars c1 
where not exists (
  select c_owner 
  from customers c2
  where c1.c_owner=c2.customer_id
);

カウント(*): 1

これは、NOT INチェックインするために特定の値が必要なためです。そのため、NULL値は として設定されFALSE、カウントされません。 NOT EXISTSセット内に要素が存在しないことを確認するため、NULL値は TRUE に設定され、含まれます。

于 2013-08-04T23:16:41.573 に答える