【问题标题】:Oracle query: WHERE NOT LIKE is not excluding record when only one record existsOracle查询:当只有一条记录时,WHERE NOT LIKE不排除记录
【发布时间】:2020-12-28 04:47:02
【问题描述】:

我有以下问题

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

因此,其中有 3 行和 Andrew,但只有一条记录带有 Marah。

如果我将查询更改为以下内容,则两个 Andrew Postings 将被正确排除

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 Postings 记录被排除在外吗?

【问题讨论】:

  • AND 在 OR 之前...
  • A AND B OR C AND D == (A AND B) OR (C AND D)。您需要放入括号以强制A AND (B OR (C AND D))。目前你有类似2 * 3 + 4 * 5的东西,当你想要类似2 * (3 + (4 * 5))
  • 您的WHERE 转换为WHERE (client_id='mamasandpapas' AND UPPER(kw) LIKE '%MARAH%') OR (UPPER(kw) LIKE '%ANDREW%' AND UPPER(kw) NOT LIKE '%KOCH%')。这是你想要的吗?
  • 我想我只是愚蠢而忘记了 AND 在 OR 之前。这个查询是由 15 年前白痴写的代码生成的。

标签: sql oracle oracle9i


【解决方案1】:

按照它的编写方式,NOT LIKE "%KOCH%" 只会在 LIKE "%ANDREW%" 评估为 True 时评估。以下是关于 Marah Koch 记录的原始 WHERE 子句的流程。

第一个 SQL 会查看 client_id 是否为 'mamasandpapas'。太好了!接下来,它看到一个 AND,这意味着它后面的任何内容也必须为真,WHERE 子句才为真,幸运的是,Upper(kw) 确实是 LIKE '%MARAH%'。然后它会看到 OR next。 SQL 决定它可以忽略其余部分,因为如果 OR 任一侧的任何表达式计算为真,那么它就完成了计算,因为 Upper(kw) LIKE '%MARAH%' 已经计算为真,所以它甚至没有到达 Upper (kw) 不喜欢 '%KOCH%'。

同样,在您的第二个 WHERE 子句示例中,它似乎只起作用,因为在 Andrew Postings 的情况下,在 client_id 评估为 true 后,AND 说查看 Upper(kw) 是否为 LIKE'%MARAH%',哦不是,现在我们移到 OR 的另一边,Upper(kw) is LIKE '%ANDREW%' 但是等等,现在我看到一个 AND,这意味着 Upper(kw) LIKE'%ANDREW%' 和其他是在另一边需要是真实的 WHERE 是真实的。如果您在 Marah Postings 表中添加一条记录,它仍会在第二个示例中返回。

为此我学到的术语是“Naked ORs”。换句话说,最好用括号“修饰”任何 OR 语句,以提高可读性,因为这是大多数人理解 AND 和 OR 逻辑的方式。

【讨论】:

    【解决方案2】:

    大概,你打算像这样where 子句:

    WHERE client_id = 'mamasandpapas' AND
          (UPPER(kw) LIKE '%MARAH%' OR UPPER(kw) LIKE '%ANDREW%' AND UPPER(kw) NOT LIKE '%KOCH%')
    

    但我不确定,因为你没有解释你想要实现的实际逻辑。也就是说,如果您将 ANDOR 混合使用,请使用括号——至少在您真正理解运算符的优先级之前这样做。

    【讨论】:

      猜你喜欢
      • 2015-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-26
      • 2012-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多