条款“丢弃”的行数多于预期

时间:2015-09-15 16:57:54

标签: sql sql-server sql-server-2008-r2 where clause

我有一个SQL Server 2008 R2查询返回“假设”100行。我实际上正在使用7k - 8k行。

Where子句是这样的:

Where Col_a = 'Y'
  And Col_b = 'N'
  And Col_c = 'X'

并且其中25行在Col_d中有'P'。

我补充说:

And Col_d = 'P'

并且查询返回了预期的25行。

然后我改为

And Col_d <> 'P'

我预计会有75行,但我只有50行。

我认为添加“And Col_d <> 'P'”只会限制'P'Col_d的行。

为什么不是这种情况,当我说Col_d <> 'P'时,我怎么弄清楚还有什么东西掉了?

正如我所说 - 我实际上是在处理更大的数字,因此观察它并不容易。

我很感激任何帮助。

谢谢!

1 个答案:

答案 0 :(得分:5)

正如评论中所述,null在进行比较时属于special case

假设以下数据。

id     someVal
----
0      null
1      1
2      2

查询:

select id
from table
where someVal = 1

将返回id 1

select id
from table
where someVal <> 1

将返回id 2

select id
from table
where someVal is null

将返回id 0

select id
from table
where someVal is not null

会返回ID 12

如果你想要空值&#34;计算&#34;作为a =&lt;&gt;中的值比较,它需要被强制转换为:

select id
from table
where isNull(someVal, -1) <> 1

返回02

或者您可以更改ANSI Null设置。

  

我想要做的只是排除那些有&#39; P&#39;在Col_d

因此,在您的特定情况下,由于您希望将Col_D中的null视为非P行,因此您的查询可能如下所示:

select * 
from someTable
Where Col_a = 'Y'
  And Col_b = 'N'
  And Col_c = 'X'
  And isNull(Col_D, 'someArbitraryValue') <> 'P'

您必须执行上述操作,因为正如我在整个答案和链接null中所指出的那样,不会将值与值进行比较。您需要使null非空的内容(使用isNull(Col_D, 'someArbitraryValue')完成)或更改ANSI NULL设置,以便将其与等值或不等于某个值进行比较。

或者@Andrew指出magic numbers是坏的(someArbitraryValue),所以你可以改为:

select * 
from someTable
Where Col_a = 'Y'
  And Col_b = 'N'
  And Col_c = 'X'
  And (Col_D <> 'P' OR Col_D is null)

通常情况下,我会直接进行上面的查询,我这样做是为了主要指出空值比较与值之间的差异。