NOT条件,排除NULL值

时间:2019-08-29 11:05:51

标签: sql sql-server tsql

我有以下示例数据。

此查询返回我需要的数据:

select * from #temp
where (Field1 = 'Test1' or Field1 = 'Test10') and
        Field2 = 'Test2' and  
        (Field3 = 'Test3' or Field3 = 'Test30')

但是,我需要另一个查询,该查询基本上显示不满足上述条件的记录(异常查询)。

如果我使用以下查询,则不会显示NULL值。这是为什么?如何获取带有NULL值的行以显示?

select * from #temp
where NOT (Field1 = 'Test1' or Field1 = 'Test10') and NOT
        Field2 = 'Test2' and   NOT
        (Field3 = 'Test3' or Field3 = 'Test30')

Create Table #temp
(
    ID int,
    Field1 varchar(50),
    Field2 varchar(50),
    Field3 varchar(50)
)

Insert into #temp
(
    ID,
    Field1,
    Field2,
    Field3
)
select
    1,
    'Test1',
    'Test2',
    'Test3'
union all
select
    2,
    NULL,
    NULL,
    NULL
union all
select
    3,
    'Test',
    'Test',
    'Test'

2 个答案:

答案 0 :(得分:3)

几乎所有与NULL的比较都返回NULL,这被视为错误。

一种相当昂贵的方法是使用EXCEPT

select t.*
from #temp t
except
select t.*
from #temp t
where (Field1 = 'Test1' or Field1 = 'Test10') and
      Field2 = 'Test2' and  
      (Field3 = 'Test3' or Field3 = 'Test30');

请注意,这将消除重复的行。

我将条款简化为:

where Field1 in ('Test1', 'Test10') and
      Field2 = 'Test2' and  
      Field3 in ('Test3', 'Test30');

很显然,您可以重构where子句以将null的值考虑在内。这确实很麻烦并且容易出错。因此,另一种方法是创建一个标志并仅使用该标志:

select t.*
from #temp t cross apply
     (values (case when (Field1 = 'Test1' or Field1 = 'Test10') and
                        Field2 = 'Test2' and  
                        (Field3 = 'Test3' or Field3 = 'Test30')
                   then 1 else 0
              end)
      ) v(flag)

然后:

 where v.flag = 1   -- for inclusion
 where v.flag = 0   -- for exclusion

答案 1 :(得分:1)

NULL不等于任何值,也不不同于任何值。他们是未知的。

要处理空值,可以使用IS NULL和IS NOT NULL。

SELECT * FROM #temp
WHERE (
Field1 NOT IN ('Test1', 'Test10')
    OR Field1 IS NULL) 
AND (Field2 <> 'Test2' OR Field2 IS NULL)
AND (Field3 NOT IN ('Test3', 'Test30')
    OR Field3 IS NULL)

作为一个额外的提示,您可以更改

Field1 = 'Test1' or Field1 = 'Test10'

对于

Field1 IN ('Test1', 'Test10')