2014-01-27 47 views
3

这可能是个傻瓜,所以我会提前道歉。SQL Server Where [column] <>

说我有两个表:

| TABLE 1 | |  TABLE 2  | 
-----------------  --------------------- 
|RESULT | REASON| |ID | DESCRIPTION| 
----------------- --------------------- 
| 1 | NULL | | A | NO INTEREST| 
| 2 | A | | B | CALL CLOSED| 
| 2 | B | | C | DECEASED | 
| 1 | NULL | --------------------- 
----------------- 

所以,REASON只能有一个值,如果RESULT为2。否则,它是NULL

现在假设我运行以下命令:

SELECT 
    t1.RESULT, t2.DESCRIPTION 
FROM 
    [TABLE 1] t1 LEFT OUTER JOIN 
    [TABLE 2] t2 ON t1.RESULT = t2.ID 

我们会得到如下:

------------------------ 
| RESULT | DESCRIPTION | 
------------------------ 
| 1 |  NULL | 
| 2 | NO INTEREST | 
| 2 | CALL CLOSED | 
| 1 |  NULL | 
------------------------ 

现在我发现,如果我再加入一个WHERE子句,像这样:

SELECT 
    t1.RESULT, t2.DESCRIPTION 
FROM 
    [TABLE 1] t1 LEFT OUTER JOIN 
    [TABLE 2] t2 ON t1.RESULT = t2.ID 
WHERE 
    t2.DESCRIPTION <> 'CALL CLOSED' 

我由于某种原因结束以下内容:

------------------------ 
| RESULT | DESCRIPTION | 
------------------------ 
| 2 | NO INTEREST | 
------------------------ 

添加where子句看起来会排除结果为1的所有记录,所有记录都带有NULL原因值/说明值。

我在这里错过了什么?

+3

与'NULL'的任何比较产生“未定义”。所以'NULL ='CALL CLOSED'和'NULL <>'CALL CLOSED'都不是真的。如果你想包含NULL值,可以使用'<>'CALL CLOSED'或t2.DESCRIPTION IS NULL' –

+0

,可能是因为左连接无法找到t2行来加入,所以无法进行比较。 – dcarneiro

+0

与问题无关,但是您的意思是“ON t1.REASON = t2.ID'? –

回答

3

在SQL中,NULL不是一个“空值”或类似的东西,它是一个缺乏值 - 对它的任何操作,期望值将返回未知。 由于未知不成立,因此在查询中不会返回where子句中返回未知条件的每行评估值。

使用<>运算符考虑您的条件为询问“描述的值是否与'CALL CLOSED'不同' - 答案为否,因为它根本没有值。

一旦我们已经确定,操作很简单 - 只需检查NULL明确:

SELECT 
    t1.RESULT, t2.DESCRIPTION 
FROM 
    [TABLE 1] t1 LEFT OUTER JOIN 
    [TABLE 2] t2 ON t1.RESULT = t2.ID 
WHERE 
    t2.DESCRIPTION IS NULL OR t2.DESCRIPTION <> 'CALL CLOSED' 
+4

“期望值的任何操作都将返回false”。 - 这是不正确的。 'NULL'强制第三个真值'UNKNOWN'。这可以通过例如(描述<>'CALL CLOSED')' - 如果Description <>'CALL CLOSED'''返回'false'为'NULL',那么'NOT'应该强制该条件成立。事实并非如此。 –

+0

@Damien_The_Unbeliever你是正确的,我在简化的事情上,到了不正确的地步。编辑我的帖子是为了更准确。顺便说一句,感谢“不”这个例子 - 这是一种非常优雅的解释方式! – Mureinik

2

为了避免丢失表1行,您可以在左侧添加表2过滤谓词JOIN条件而不是:

SELECT 
    t1.RESULT, t2.DESCRIPTION 
FROM 
    [TABLE 1] t1 LEFT OUTER JOIN 
    [TABLE 2] t2 ON t1.RESULT = t2.ID AND t2.DESCRIPTION <> 'CALL CLOSED' 

这样你表达你想从表1中的所有行,并从表2时,表2列相匹配的连接条件说明。

相关问题