在WHERESQL 查询的子句中,我希望这两个条件具有相同的行为:
NOT (a=1 AND b=1)
Run Code Online (Sandbox Code Playgroud)
对比
a<>1 AND b<>1
Run Code Online (Sandbox Code Playgroud)
第一个条件的行为符合预期,虽然我希望第二个条件做同样的事情,但事实并非如此。
这是非常基本的东西,但可耻的是我看不出我做错了什么。
Len*_*art 47
它们不是等价的。
NOT (a=1 AND b=1)
Run Code Online (Sandbox Code Playgroud)
相当于:
(NOT a=1 OR NOT b=1) <=> (a<>1 OR b<>1)
Run Code Online (Sandbox Code Playgroud)
这种等价称为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
Run Code Online (Sandbox Code Playgroud)
编辑:由于 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;
Run Code Online (Sandbox Code Playgroud)
查询的结果是:
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)
Run Code Online (Sandbox Code Playgroud)
如图所示,exp1 和 exp2 是等价的。
你的第一个例子是说:
返回所有行除了其中两个A = 1 AND B = 1
你的第二个例子是说:
返回所有行除外,其中任一A = 1 OR 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);
Run Code Online (Sandbox Code Playgroud)
这将返回以下结果
a b
0 0
1 0
0 1
Run Code Online (Sandbox Code Playgroud)