T-SQL: 选择不等于某个值的行,包括空值。

30

如何选择不等于某个值的行并在返回的数据中包含空值?我尝试过:

SET ANSI_NULLS OFF
SELECT TOP 30 FROM Mails
WHERE assignedByTeam <> 'team01'

我想返回不在“assignedByTeam”列中具有“team01”的行,但我也希望结果包含空值。不幸的是,上面的代码不起作用(不返回空值)。

我正在使用MS SQL Server 2008 Express。

5个回答

34

尝试显式地检查NULL:

SELECT TOP 30 col1, col2, ..., coln
FROM Mails
WHERE (assignedByTeam <> 'team01' OR assignedByTeam IS NULL)

1
嗯,是的,但我认为有一种更短的方法来完成这个任务,比起写几个命令,只需要一个命令就可以了。无论如何,感谢你的努力! - Val
6
在SQL标准中,有一个名为“IS DISTINCT FROM”的运算符可以实现这个功能,但是SQL Server不支持。MySQL有一个非标准的空值安全等号运算符“NOT a <=> b”,但是SQL Server也不支持这种写法。 - Mark Byers

20
SELECT TOP 30 FROM Mails
WHERE ISNULL(AssignedByTeam,'') <> 'team01'

我看到了一个使用COALESCE语句的版本,但ISNULL()更高效。


2
在我看来,这是最优雅的解决方案。 - Amarundo
1
那个执行计划看起来是什么样子的?它还会使用索引吗? - Jonathan Allen
1
索引将不会被使用。为了提高性能,WHERE (assignedByTeam <> 'team01' OR assignedByTeam IS NULL) 更好。 - Reversed Engineer
@ReversedEngineer 索引对于不等于运算符(<>)有效吗?你必须找到除了team01之外的所有值。所以这已经无法通过索引进行搜索了。 - doctorgu
@ReversedEngineer 可能是优化器选择了这种方式,但我认为它与完全扫描表没有区别。因为Oracle不能在索引叶的左侧和右侧结束之前停止查找。而对于这种情况最糟糕的事情是null值没有被索引,所以Oracle必须进行完全扫描才能找到null值。 - doctorgu
显示剩余2条评论

12

当你有很多条件时,打两次所有内容会非常麻烦。以下是两种更好的选择:

SELECT TOP 30 FROM Mails
WHERE COALESCE(assignedByTeam,'') <> 'team01'

COALESCE运算符返回列表中第一个非空值。如果assignedByTeam不为空,则会将assignedByTeam值与'team01'进行比较。但是,如果assignedByTeam为空,它将把空白''与'team01'进行比较。这基本上是以下内容的缩写:

SELECT TOP 30 FROM Mails
WHERE (CASE WHEN assignedByTeam IS NULL THEN '' ELSE assignedByTeam END) <> 'team01'

第二种方法是将您的条件设为有条件的,例如:
SELECT TOP 30 FROM Mails
WHERE 1 = CASE WHEN assignedByTeam = 'team01' THEN 0 ELSE 1 END

在这个例子中,ELSE 值将包括所有空行,因为它们不等于 'team01'。

4
SELECT TOP 30 FROM Mails
WHERE assignedByTeam <> 'team01'
OR assignedByTeam is null

2
 where column != 'value' or column is null

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接