NOT(a = 1 AND b = 1)vs(a <> 1 AND b <> 1)


16

ではWHERE、SQLクエリの句私は、これら2つの条件が同じ振る舞いを持つことを期待します:

NOT (a=1 AND b=1)

a<>1 AND b<>1

最初の条件は期待どおりに動作し、2番目の条件を実行して同じことを行いますが、そうではありません。

これは非常に基本的なことですが、恥ずかしいことに、私が間違っていることを見ることができません。


サンプルデータと期待される結果と実際の結果を投稿できますか?
ガレスライオンズ

6
Lenardの答えで述べたように、これはDe Morganルールの例です:not(A and B)=(not not A)or(not not B)not(A or B)=(not A)and(not B)。NULL値には注意してください。
バランカ

2
英語で考えてみてください。あなたの最初は「私がフランスの王であり、人間であるということではありません」-非常に真実です。あなたの2番目は「私はフランスの王でも人間でもありません」-非常に間違っています。
パトリックスティーブンス

3
これは「De Morganの法則」と矛盾しています。同等のものはになりますa <> 1 OR b<>1
ウィレムヴァンOnsem

回答:


46

それらは同等ではありません。

NOT (a=1 AND b=1)

と同等です:

(NOT a=1 OR NOT b=1) <=> (a<>1 OR b<>1)

この等価性はとして知られていDe Morgan's Lawます。例を参照してください:

https://en.wikipedia.org/wiki/De_Morgan%27s_laws

ブール代数式の等価性を証明/反証するための優れた手法は、ドメインにcteを使用し、式を並べて比較することです。

with T(a) as ( values 0,1 )
   , U(a,b) as (select t1.a, t2.a as b 
               from t as t1 
               cross join t as t2
) 
select a,b
    , case when not (a=1 and b=1) then 1 else 0 end
    , case when a<>1 and b<>1 then 1 else 0 end 
from U

A           B           3           4          
----------- ----------- ----------- -----------
          0           0           1           1
          0           1           1           0
          1           0           1           0
          1           1           0           0

編集:DB2はブールデータ型をサポートしていないため、例を次の場所に拡張しました。

http://sqlfiddle.com/#!15/25e1a/19

書き換えられたクエリは次のようになります。

with T(a) as ( values (0),(1),(null) )
   , U(a,b) as (select t1.a, t2.a as b 
                from t as t1 
                cross join t as t2
) 
select a,b
     , not (a=1 and b=1) as exp1 
     , a<>1 or b<>1 as exp2
from U;

クエリの結果は次のとおりです。

a       b       exp1        exp2
--------------------------------
0       0       true        true
0       1       true        true
0       (null)  true        true
1       0       true        true
1       1       false       false
1       (null)  (null)      (null)
(null)  0       true        true
(null)  1       (null)      (null)
(null)  (null)  (null)      (null)

示されているように、exp1とexp2は同等です。


16
De Morganに言及するためだけに+1。あらゆる形式のプログラミング/スクリプト作成を行うすべての人が読む必要があります。
トニー

しかし、NULLはどうですか?
dan04

@ dan04最初の行にNULLを追加できます(with T(a) as ( values 0,1,NULL )クエリになり、クエリを再実行すると、何が起こるかがわかります。NULL は、学習したほとんどの設定された同値ルールで間違いなくレンチを投げます。短い答えはa = NULLおよびa < > NULLは両方ともNULLを生成するため、elseケースに分類されます。さらに読むには:(stackoverflow.com/questions/1833949/…
ブライアンJ

DB2の最初の例を修正しなければならなかった理由はわかりません。私に示されているように動作します。DB2 LUWではなくDB2 for iを使用しています。2番目の例には、DB2 for iの構文エラーがいくつかあります。
jmarkmurphy

@jmarkmurphy、私はDB2 for iを知りません。おそらくそこで動作します。LUWの場合、case式は0または1にマップされるため、nullも含めるように変更する必要があります。そうすることで、ケース式はもはや自明ではなくなり(IMO)、式について推論することが難しくなります。
レナート

9

最初の例は次のとおりです。

すべての行を返す以外どこの両方、A = 1 AND B = 1

2番目の例は次のとおりです。

すべての行を返す以外のいずれか = 1 OR B = 1

2番目のクエリで最初のクエリと同じ結果が返されるようにするANDには、OR

CREATE TABLE #Test (a BIT, b BIT);

INSERT INTO #Test
        ( a, b )
VALUES
        ( 0, 0 ),
        ( 1, 0 ),
        ( 0, 1 ),
        ( 1, 1 );

SELECT * FROM #Test AS t
WHERE NOT (a=1 AND b=1);

SELECT * FROM #Test AS t
WHERE (a <> 1 OR b <> 1);

これにより、次の結果が返されます

a   b
0   0
1   0
0   1

a<>1 AND b<>1「a = 1 OR b = 1」に変換される理由を説明していただけますか?
-doub1ejack

1
@ doub1ejack、最初のステートメントと同等にするには、2番目のステートメントに追加の否定が必要ですNOT ( a=1 OR b=1 )。不幸な自然言語にはあいまいさが含まれており、論理式を自然言語に、またはその逆に変換することは困難です。例えば、ないneither a=1 nor b=1意味NOT ( a=1 OR b=1 )(NOT a=1) OR (NOT b=1)
レナート

1
@ doub1ejack「車は赤で4つのドアがあります」の反対は、「車が赤ではない、または4つのドアがない」です。ステートメントを真にするために複数のことを真にする必要がある場合、偽にする必要があるのはそのうちの1つだけです。
ホッブズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.