Where Clause 'drops' 行数比预期多
Where Clause 'drops' more rows than expected
我有一个 SQL Server 2008 R2 查询返回 "hypothetically" 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'
”只会限制 Col_d
中有 'P'
的行。
为什么不是这样,当我说 And Col_d <> 'P'
?
时,我如何弄清楚还有什么东西被丢弃了
正如我所说的 - 我实际上正在处理更大的数字,所以要用眼睛观察它并不容易。
如有任何帮助,我将不胜感激。
谢谢!
如评论中所述,null
在比较方面是 special case。
假设以下数据。
id someVal
----
0 null
1 1
2 2
有查询:
select id
from table
where someVal = 1
会return id 1
select id
from table
where someVal <> 1
会return id 2
select id
from table
where someVal is null
会return id 0
select id
from table
where someVal is not null
return 两个 ID 1
和 2
。
如果您希望空值 "counted" 作为 = <> 比较中的值,则需要将其强制转换为:
select id
from table
where isNull(someVal, -1) <> 1
returns 0
和 2
或者您可以更改 ANSI Null 设置。
What I want to do is only exclude the rows that have 'P' in 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)
通常我会直接执行上面的查询,我用另一种方式来做,主要是为了指出 null 比较与值之间的差异。
我有一个 SQL Server 2008 R2 查询返回 "hypothetically" 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'
”只会限制 Col_d
中有 'P'
的行。
为什么不是这样,当我说 And Col_d <> 'P'
?
正如我所说的 - 我实际上正在处理更大的数字,所以要用眼睛观察它并不容易。
如有任何帮助,我将不胜感激。
谢谢!
如评论中所述,null
在比较方面是 special case。
假设以下数据。
id someVal
----
0 null
1 1
2 2
有查询:
select id
from table
where someVal = 1
会return id 1
select id
from table
where someVal <> 1
会return id 2
select id
from table
where someVal is null
会return id 0
select id
from table
where someVal is not null
return 两个 ID 1
和 2
。
如果您希望空值 "counted" 作为 = <> 比较中的值,则需要将其强制转换为:
select id
from table
where isNull(someVal, -1) <> 1
returns 0
和 2
或者您可以更改 ANSI Null 设置。
What I want to do is only exclude the rows that have 'P' in 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)
通常我会直接执行上面的查询,我用另一种方式来做,主要是为了指出 null 比较与值之间的差异。