5

私はこの興味深い行動に出くわしました。左結合が進むべき道だと思いますが、それでもこれをクリアしたいと思います。それはバグですか、それとも設計による動作ですか?説明はありますか?

左側のテーブルからレコードを選択すると、右側のテーブルのサブクエリの結果に値が存在しない場合、サブクエリの結果にnullが含まれていると、予期される「欠落している」レコードは返されません。このクエリを作成する2つの方法は同等であると期待していました。

ありがとう!

declare @left table  (id int not null primary key identity(1,1), ref int null)
declare @right table (id int not null primary key identity(1,1), ref int null)

insert @left (ref) values (1)
insert @left (ref) values (2)

insert @right (ref) values (1)
insert @right (ref) values (null)

print 'unexpected empty resultset:'
select * from @left
where ref not in (select ref from @right)

print 'expected result - ref 2:'
select * from @left
where ref not in (select ref from @right where ref is not null)

print 'expected result - ref 2:'
select l.* from @left l
  left join @right r on r.ref = l.ref
where r.id is null

print @@version

与える:

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)
unexpected empty resultset:
id          ref
----------- -----------

(0 row(s) affected)

expected result - ref 2:
id          ref
----------- -----------
2           2

(1 row(s) affected)

expected result - ref 2:
id          ref
----------- -----------
2           2

(1 row(s) affected)

Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64) 
    Apr  2 2010 15:48:46 
    Copyright (c) Microsoft Corporation
    Standard Edition (64-bit) on Windows NT 6.0 <X64> (Build 6002: Service Pack 2) (Hypervisor)
4

4 に答える 4

8

これは仕様によるものです。一致が失敗し、セットにNULLが含まれている場合、SQL標準で指定されているように、結果はNULLになります。

'1' IN( '1'、 '3')=> true
'2' IN( '1'、 '3')=> false
'1' IN( '1'、NULL)=> true
'2' IN( '1'、NULL)=> NULL

'1' NOT IN( '1'、 '3')=> false
'2' NOT IN( '1'、 '3')=> true
'1' NOT IN( '1'、NULL)=> false
'2' NOT IN( '1'、NULL)=> NULL

非公式には、この背後にある論理は、NULLは未知の値と考えることができるということです。たとえば、ここでは不明な値が何であるかは関係ありません。「1」は明らかにセットに含まれているため、結果は真になります。

'1' IN ('1', NULL) => true

次の例では、「2」がセットに含まれていることを確認できませんが、すべての値がわからないため、セットに含まれていないことも確認できませ。したがって、結果はNULLになります。

'2' IN ('1', NULL) => NULL

別の見方は、x NOT IN (Y, Z)として書き直すことX <> Y AND X <> Zです。次に、 3値論理のルールを使用できます。

true AND NULL => NULL
false AND NULL => false
于 2010-12-27T14:31:56.327 に答える
3

はい、これが設計された方法です。LEFT JOINaまたはaを実行することの間には、他にも多くの考慮事項がありNOT INます。この動作の非常に良い説明があるために、このリンクを見る必要があります。

于 2010-12-27T14:43:07.200 に答える
0

これが、ANSI委員会が行う必要があると考える方法です。

クエリの前に

set ansi_defaults OFF

そしてあなたはあなたが期待する結果を得る。

SQL-Server 7.0以降、Microsoftはansi標準に従うことにかなり厳格です。

編集:

デフォルトと戦わないでください。あなたは結局あきらめるでしょう。

于 2010-12-27T14:39:15.003 に答える
0

動作の根本的な原因は、マークによって説明されています。これは、複数の方法で解決できます。たとえば、LEFT JOIN、where句またはselect句から、相互に関連するサブクエリを使用してNULL値を除外することにより、内部クエリからNULL値をフィルタリングします。

次の3つの短い投稿は、同じ主題に関するケーススタディです。- NOTINサブクエリはゼロ行を返します-問題、NOT INサブクエリはゼロ行を返します-ルート原因、NOTINサブクエリゼロ行を返します-回避策

于 2014-03-08T15:01:23.557 に答える