问题描述
select cand_id
from cand_kw
WHERE client_id='mamasandpapas' AND UPPER(kw) LIKE '%MaraH%' OR UPPER(kw) LIKE '%ANDREW%' AND UPPER(kw) NOT LIKE '%KOCH%'
数据库中包含以下记录:
Andrew Postings
Andrew Postings
Andrew McDee
Marah Koch
因此,其中有安德鲁(Andrew)的三行,但其中只有马拉(Marah)的记录。
如果我将查询更改为以下内容,则将两个Andrew帖子排除在外
select cand_id
from cand_kw
WHERE client_id='mamasandpapas' AND UPPER(kw) LIKE '%MaraH%' OR UPPER(kw) LIKE '%ANDREW%' AND UPPER(kw) NOT LIKE '%POSTINGS%'
因此,看起来好像只有一条记录存在,即使将结果排除在外,也会返回结果。
这使用的是Oracle(9i)的非常旧的版本,其搜索(kw)字段代表关键字,并且是包含一堆关键字的CLOB。
这是我设计的非常老的系统。
在第一种情况下,谁能解释为什么不排除Marah Koch而将Andrew Posts记录排除在外?
解决方法
大概,您打算使用类似where
的子句:
WHERE client_id = 'mamasandpapas' AND
(UPPER(kw) LIKE '%MARAH%' OR UPPER(kw) LIKE '%ANDREW%' AND UPPER(kw) NOT LIKE '%KOCH%')
但是我不确定,因为您没有解释要实现的实际逻辑。也就是说,如果您要混合使用AND
和OR
,请使用括号-至少要等到您真正了解运算符的优先级之后。
编写方式,仅当“%ANDREW%”的评估结果为True时,才会评估“不喜欢”的“%KOCH%”。这是关于Marah Koch记录的原始WHERE子句的流程。
第一个SQL查看client_id是否为'mamasandpapas'。太好了!接下来,它看到一个AND,这意味着WHERE子句为true时必须遵循的所有条件也必须为真,幸运的是,Upper(kw)确实像'%MARAH%'。然后,接下来看到“或”。 SQL决定它可以忽略其余部分,因为如果OR两侧的任何表达式的求值都为true,那么它就已经完成求值,因为Upper(kw)LIKE'%MARAH%'已经求值为true,所以它甚至都没有达到Upper (kw)不喜欢'%KOCH%'。
同样,在您的第二个WHERE子句示例中,它似乎仅能工作,因为在Andrew Postings的情况下,在client_id评估为true之后,AND会说Upper(kw)是否为LIKE'%MARAH%',哦不是,现在我们移至OR的另一侧,Upper(kw)为LIKE'%ANDREW%',但请稍等,现在我看到一个AND,这意味着Upper(kw)就像'%ANDREW%'另一方面,“ WHERE”必须为真。如果您将记录添加到您的Marah Posts表中,该记录仍将在第二个示例中返回。
为此我学到的术语是“裸OR”。换句话说,为便于阅读,最好用括号将所有OR语句“修饰”,因为这是大多数人理解AND和OR逻辑的方式。