组合AND OR结果

时间:2015-06-08 12:26:26

标签: sql sql-server

我有一张这样的表。

NoteID  CustomerID  CustomerName    Note                    Type    Date    Active
6       81          Paris           test                    Info    2015-06-04  1
10      81          Rotterdam       Everything is allright  Comment 2015-06-04  1
11      81          Hamburg         Everything is allright  Info    2015-06-04  1
12      81          Hamburg         Everything is allright  Info    2015-06-04  1
13      81          Amsterdam       Everything is allright  Info    2015-06-04  1
14      81          Rotterdam       Everything is allLeft   Comment 2015-06-04  1
15      81          Hamburg         Everything is allLeft   Info    2015-06-04  1
16      81          Hamburg         Everything is allLeft   Info    2015-06-04  1
17      81          Amsterdam       Everything is allLeft   Info    2015-06-04  1

当我执行此查询时:

SELECT *
  FROM CarsNote
  WHERE Note LIKE '%ddddddddddddddd%' 
  AND Type != 'Comment' 
  OR Type != 'error'

结果中包含所有注释。

我的期望是结果中没有注释。由于LIKE声明'%ddddddddddddddd%'

有人可以解释为什么这个查询没有像我预期的那样工作吗?

6 个答案:

答案 0 :(得分:13)

不确定。它被称为运算符优先级(或更一般地,运算符评估顺序)。

如果您添加括号,这就是您正在评估的内容:

WHERE ((Note LIKE '%ddddddddddddddd%') AND Type != 'Comment') OR Type != 'error'

根据MSDN:

  

当在语句中使用多个逻辑运算符时,首先计算NOT,然后计算AND,最后计算OR。算术运算符和按位运算符在逻辑运算符之前处理。

NOT部分很棒 - 这意味着你可以摆脱不必要的括号。其余的更复杂一点 - AND将始终优先于OR,其他条件相同。这也意味着蒂姆的第二个建议实际上会起作用 - 但是,不,不要这样做。这太疯狂了。

即使你知道操作员评估的规则,也不要明白它是一个坏主意 - 它太脆弱了,更不用说难以阅读了(我' m目前使用的代码库充满了这样的东西 - 只是不要。你将来会为自己和其他所有人节省很多麻烦。)只需使用它:

where Note like '%ddddddddddddddd%' or not (Type = 'Comment' or Type = 'Error')

甚至更好,

where Note like '%ddddddddddddddd%' and Type not in ('Comment', 'Error')

答案 1 :(得分:7)

您有两种选择:

  1. OR包裹在paranthesis
  2. 重复AND + OR
  3. 第一种方法(*):

    SELECT *
    FROM CarsNote
    WHERE Note LIKE '%ddddddddddddddd%' 
     AND (Type != 'Comment' OR Type != 'error')
    

    第二

    SELECT *
    FROM CarsNote
    WHERE Note LIKE '%ddddddddddddddd%' AND Type != 'Comment' 
       OR Note LIKE '%ddddddddddddddd%' AND Type != 'error'
    

    我更喜欢第一个,因为它更简洁,更不容易出错。

    *重要说明:两种方法都没有意义,因为!=OR的组合始终为true,它会删除过滤器并返回所有记录。实际上你必须使用AND

    WHERE Note LIKE '%ddddddddddddddd%' 
    AND (Type != 'Comment' AND Type != 'error')
    

    您不需要使用AND

    的paranthesis
    WHERE Note LIKE '%ddddddddddddddd%' 
      AND Type != 'Comment' AND Type != 'error'
    

    如果您想要包含/排除多个值,使用IN / NOT IN会更具可读性:

    WHERE Note LIKE '%ddddddddddddddd%' 
    AND Type NOT IN('Comment', 'error')
    

    请注意,这会跳过TypeNULL的记录。因此你必须使用:

    WHERE Note LIKE '%ddddddddddddddd%' 
    AND (Type IS NULL OR Type NOT IN('Comment', 'error'))
    

答案 2 :(得分:3)

组合时始终使用parantheses:

function Person() {}

Person.prototype.Name      = "";
Person.prototype.Lastname  = "";

var NewPerson= new Person();

NewPerson.Name      = "Nancy";
NewPerson.Lastname  = "Drew";   //<--- right way

NewPerson.lastname  = "Drew";   //<--- wrong property

您还可以使用SELECT * FROM CarsNote WHERE Note LIKE '%ddddddddddddddd%' AND (Type != 'Comment' OR Type != 'error')

NOT IN

答案 3 :(得分:3)

您对此SQL的评论是:

  

使用d ... d等注释向我显示所有记录,而不是“注释”类型,其中类型不是“错误”

在 OR之前执行AND语句。它可以写成:

(Note LIKE '%ddddddddddddddd%' AND Type != 'Comment') OR Type != 'error'

我猜您需要的是:

Note Like '%ddddddddddddddd%' AND (Type != 'Comment' OR Type != 'error')

答案 4 :(得分:2)

在下面的代码段中添加我提到的括号。 OR导致了这种情况,因为没有类型是=&#39;错误&#39;

SELECT *
FROM CarsNote
WHERE Note LIKE '%ddddddddddddddd%' 
AND (Type != 'Comment' 
OR Type != 'error')

答案 5 :(得分:0)

尝试始终在where子句上使用括号来显式设置顺序。 我认为这是最好的做法。