COUNT()函数与NOT IN子句一起使用无法与varchar字段(T-SQL)一起使用

时间:2010-02-25 20:37:47

标签: sql sql-server tsql null not-exists

在尝试计算没有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子句中的任何内容)。我希望我能说清楚,有人可以帮助我。

提前致谢。

2 个答案:

答案 0 :(得分:6)

对于NOT IN,如果子查询返回NULL值,则始终为false。 this question接受的答案优雅地描述了原因。

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

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

SELECT COUNT(*) FROM SomeTable S1 
WHERE NOT EXISTS (SELECT * FROm SomeOtherTable S2 WHERE S1.[MyField] = S2.MyOtherField)   

答案 1 :(得分:0)

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

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