组合AND OR结果

JP.*_*..t 3 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
Run Code Online (Sandbox Code Playgroud)

当我执行此查询时:

SELECT *
  FROM CarsNote
  WHERE Note LIKE '%ddddddddddddddd%' 
  AND Type != 'Comment' 
  OR Type != 'error'
Run Code Online (Sandbox Code Playgroud)

所有笔记都在结果中.

我的期望是结果中没有注释.因为LIKE声明'%ddddddddddddddd%'.

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

Lua*_*aan 13

当然.它被称为运算符优先级(或更一般地,运算符评估顺序).

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

WHERE ((Note LIKE '%ddddddddddddddd%') AND Type != 'Comment') OR Type != 'error'
Run Code Online (Sandbox Code Playgroud)

根据MSDN:

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

NOT部分很棒 - 这意味着你可以摆脱不必要的括号.其余的更复杂一点 - AND总是优先OR,其他一切都相等.这也意味着蒂姆的第二个建议确实有效 - 但是,不要这样做.这太疯狂了.

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

where Note like '%ddddddddddddddd%' or not (Type = 'Comment' or Type = 'Error')
Run Code Online (Sandbox Code Playgroud)

甚至更好,

where Note like '%ddddddddddddddd%' and Type not in ('Comment', 'Error')
Run Code Online (Sandbox Code Playgroud)

  • 在我看来,"NOT IN"使查询的意图最清晰. (4认同)

Tim*_*ter 7

您有两种选择:

  1. 包裹OR在paranthesis
  2. 重复AND+OR

第一种方法(*):

SELECT *
FROM CarsNote
WHERE Note LIKE '%ddddddddddddddd%' 
 AND (Type != 'Comment' OR Type != 'error')
Run Code Online (Sandbox Code Playgroud)

第二:

SELECT *
FROM CarsNote
WHERE Note LIKE '%ddddddddddddddd%' AND Type != 'Comment' 
   OR Note LIKE '%ddddddddddddddd%' AND Type != 'error'
Run Code Online (Sandbox Code Playgroud)

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

*重要提示:这两种方法都因为组合毫无意义!=,并OR始终是真实的,它消除了过滤器和返回所有记录.所以实际上你必须使用AND:

WHERE Note LIKE '%ddddddddddddddd%' 
AND (Type != 'Comment' AND Type != 'error')
Run Code Online (Sandbox Code Playgroud)

你不需要parance AND:

WHERE Note LIKE '%ddddddddddddddd%' 
  AND Type != 'Comment' AND Type != 'error'
Run Code Online (Sandbox Code Playgroud)

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

WHERE Note LIKE '%ddddddddddddddd%' 
AND Type NOT IN('Comment', 'error')
Run Code Online (Sandbox Code Playgroud)

请注意,这会跳过记录所在的Type位置NULL.因此你必须使用:

WHERE Note LIKE '%ddddddddddddddd%' 
AND (Type IS NULL OR Type NOT IN('Comment', 'error'))
Run Code Online (Sandbox Code Playgroud)