日期:2014-05-17  浏览次数:20580 次

疑难杂症:and和or
问题:一张表tj_lmj_sp_1有如下字段:(spid varchar(255),cpid varchar(30),acct_item_type_id decimal(9,0),acct_item_type_name varchar(200),charge decimal(16,5))
现要求:排除所有spid为0或为null的记录,并且排除所有cpid为0或为null的记录,然后求sum(charge)。

根据此要求,写出的sql如下:
sql1:
select sum(charge) from 
(select * 
 from (select * from tj_lmj_sp_1 where cpid is not null and cpid <> 0) a
 where spid is not null and spid <> 0
) b

另外换种写法,结果正确:
sql2:
select spid,cpid,acct_item_type_id,acct_item_type_name,sum(charge)
from tj_lmj_sp_1
where (spid is not null and spid <> 0)  --排除所有spid为0或为null的
  and (cpid is not null and cpid <> 0)  --排除所有cpid为0或为null的
group by  spid,cpid,acct_item_type_id,acct_item_type_name

再换种写法,结果错误:
sql3:
select spid,cpid,acct_item_type_id,acct_item_type_name,sum(charge)
from tj_lmj_sp_1
where (spid is not null or spid <> 0)  --排除所有spid为0或为null的
  and (cpid is not null or cpid <> 0)  --排除所有cpid为0或为null的
group by  spid,cpid,acct_item_type_id,acct_item_type_name

sql3统计的结果中还包含有sqid=0或者是cpid=0的记录,sql3错在哪里呢?
从逻辑上看,感觉sql3是正确的,sql2是错误的,对sql2做如下变形:
select count(*) from tj_lmj_sp_1 where spid is not null and spid <> 0
select count(*) from tj_lmj_sp_1 where cpid is not null and cpid <> 0
这两句sql统计的结果一定是0,但sql2的最终结果就是正确的,sql3的结果就是错误的,这是为何?
如果把sql3 where条件里面的and换成or也是错误的,即:
select spid,cpid,acct_item_type_id,acct_item_type_name,sum(charge)
from tj_lmj_sp_1
where (spid is not null or spid <> 0)  --排除所有spid为0或为null的
   or (cpid is not null or cpid <> 0)  --排除所有cpid为0或为null的
group by  spid,cpid,acct_item_type_id,acct_item_type_name

------解决方案--------------------
引用:
现要求:排除所有spid为0或为null的记录,并且排除所有cpid为0或为null的记录,然后求sum(charge)。

根据此要求,写出的sql如下:

另外换种写法,结果正确:
sql2:
select spid,cpid,acct_item_type_id,acct_item_type_name,sum(charge)
from tj_lmj_sp_1
where (spid is not null and spid <> 0)  --排除所有spid为0或为null的
  and (cpid is not null and cpid <> 0)  --排除所有cpid为0或为null的
group by  spid,cpid,acct_item_type_id,acct_item_type_name

再换种写法,结果错误:
sql3:
select spid,cpid,acct_item_type_id,acct_item_type_name,sum(charge)
from tj_lmj_sp_1
where (spid is not null or spid <> 0)  --排除所有spid为0或为null的
  and (cpid is not null or cpid &l