SQL where子句有多个'not in'检查

时间:2010-11-19 15:32:54

标签: sql sql-server sql-server-2005 tsql

这看起来应该是一个相对简单的查询,但有人可以解释为什么第二个查询不返回第2行和第3行但第三个查询没有?基本上,我如何使查询满足'not in'子句?

declare @t table (id int identity, code1 char(2), code2 char(2))

insert into @t (code1, code2) values ('AA','BB')
insert into @t (code1, code2) values ('AA','CC')
insert into @t (code1, code2) values ('DD','EE')

select * from @t where code1 = 'AA' and code2 = 'BB'
select * from @t where (code1 != 'AA' and code2 != 'BB')
select * from @t t1 left join @t t2 on t2.id = t1.id and t2.code1 = 'AA' and t2.code2 = 'BB' where t2.id is null

*已更新 *

感谢您的回答。我希望“(code1!='AA'和code2!='BB')”都需要评估,即第1行(AA,BB)将被滤除,但rwo 2(AA,CC)将被退回。

有没有简单的方法来规定需要满足两个约束,这是我希望通过使用括号和和语句来实现的?

6 个答案:

答案 0 :(得分:2)

对于查询2,第二行code1 != 'AA'为FALSE。

答案 1 :(得分:1)

实际上查询2应该只返回第3行,因为'DD'!='AA'和'EE'!='BB'

答案 2 :(得分:1)

使第二个查询等同于您需要的第三个查询:

select * from @t where (code1 != 'AA' or code2 != 'BB')

绘制一个逻辑表来计算出来:

Row    p1 (code1 != 'AA')   p2 (code2 != 'BB')   p1 AND p2    p1 OR p2
---    ------------------   ------------------   ---------    --------
 1         false                false              false        false
 2         false                true               false        true
 3         true                 true               true         true

编辑:响应您的更新:将两个NOTS放在一起可以反直觉(再次,如果您需要了解它是如何工作的,请自己绘制一个逻辑表)。更明确的使用NOT的方法是将'NOT'移动到括号外Joe suggested

select * from @t where NOT (code1 = 'AA' or code2 = 'BB')

答案 3 :(得分:0)

第二个查询无法返回记录2,因为它显示“code1!= AA” - 对于第二条记录不是这样,所以它应该只返回记录3.

答案 4 :(得分:0)

第三个查询是左连接 - 并且t1基本上没有条件因此t1的所有行都将被返回,即使t2上存在某些条件(t2中的行将被放入的条件过滤掉,但是它是一个左连接,它不会影响由t1返回的行

答案 5 :(得分:0)

作为一般原则:LEFT JOINED表中的字段不应出现在WHERE子句中。

SELECT * FROM CUSTOMER
LEFT OUTER JOIN
ORDERS 
    ON CUSTOMER.CustomerID = ORDERS.CustomerID
WHERE ORDERS.CustomerID <> 1208

WHERE子句将其转换为INNER JOIN。 如果要排除1208,请检查ORDERS.CustomerID。