Condition
NOT (a=1 AND b=1) vs (a<>1 AND b<>1)
在
WHERE
SQL 查詢的子句中,我希望這兩個條件具有相同的行為:NOT (a=1 AND b=1)
對比
a<>1 AND b<>1
第一個條件的行為符合預期,雖然我期望第二個條件做同樣的事情,但事實並非如此。
這是非常基本的東西,但很慚愧,我看不出我做錯了什麼。
它們不是等價的。
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 是等價的。
你的第一個例子是說:
返回除a = 1 AND b = 1之外的所有行
你的第二個例子是說:
返回除a = 1或b = 1之外的所有行
要使第二個查詢返回與第一個相同的查詢,您應該將您的查詢更改
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