7

在尝试计算没有由 select 语句指定的 varchar 值的行数时,我遇到了一个奇怪的情况。好的,即使对我来说这听起来也很混乱,所以让我举个例子:

假设我在“SomeTable”中有一个字段“MyField”,我想计算有多少行 MyField 值不属于由“SomeOtherTable”中的“MyOtherField”值定义的域。换句话说,假设我有 MyOtherField = {1, 2, 3},我想计算有多少行 MyField 值不是 1、2 或 3。为此,我将使用以下查询:

SELECT COUNT(*) FROM SomeTable   
WHERE ([MyField] NOT IN (SELECT MyOtherField FROM SomeOtherTable))   

它就像一个魅力。但是请注意,MyField 和 MyOtherField 是 int 类型的。如果我尝试运行完全相同的查询,除了 varchar 类型的字段,即使我知道有错误的值,它的返回值也是 0,我把它们放在那里!但是,如果我尝试简单地通过抑制上面查询中的“NOT”子句来计算相反的(域中有多少行与我想要的有多少行相反)......好吧,那作品!¬¬

是的,必须有很多解决方法,但我想知道为什么它不能按应有的方式工作。此外,我不能简单地更改整个查询,因为它的大部分是在 C# 代码中构建的,基本上我可以自由更改且不会对软件的任何其他部分产生影响的唯一部分是 select 语句对应于域(NOT IN 子句中的任何内容)。我希望我说清楚了,有人可以帮助我。

提前致谢。

4

2 回答 2

6

对于 NOT IN,如果子查询返回 NULL 值,则始终为 false。这个问题的公认答案优雅地描述了原因。

列值的 NULLability 也与使用的数据类型无关:很可能您的 varchar 列具有 NULL 值

处理这个,使用NOT EXISTS。对于非空值,它的工作方式与 NOT IN 相同,因此兼容

SELECT COUNT(*) FROM SomeTable S1 
WHERE NOT EXISTS (SELECT * FROm SomeOtherTable S2 WHERE S1.[MyField] = S2.MyOtherField)   
于 2010-02-25T20:47:02.250 回答
0

gbn 有一个更完整的答案,但我懒得记住所有这些。相反,我有从我的 IN 子句中过滤空值的宗教习惯:

SELECT COUNT(*)
FROM SomeTable    
WHERE [MyField] NOT IN (
  SELECT MyOtherField FROM SomeOtherTable
  WHERE MyOtherField is not null
)
于 2010-02-25T21:31:08.917 回答