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

condition

In the WHERE clause of a SQL query I would expect these two conditions to have the same behavior:

NOT (a=1 AND b=1)

vs

a<>1 AND b<>1

The first condition behaves as expected, and while I epxect the second condition to do the same thing, it does not.

This is very basic stuff, but ashamedly I can't see what I'm doing wrong.

Best Answer

They are not equivalent.

NOT (a=1 AND b=1)

is equivalent with:

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

This equivalence is known as De Morgan's Law. See for example:

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

A nice technique for proving/disproving equivalences for boolean algebra expressions is to use a cte for the domains, and compare the expressions side by side:

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

Edit: Since DB2 does not support Boolean datatype I expanded the example at:

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

The rewritten query looks like:

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;

The result of the query is:

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)

As shown exp1 and exp2 are equivalent.