You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle多字段取反查询失效,求错误排查及正确写法

问题排查与正确SQL写法

我来帮你梳理下这个SQL的问题,你遇到的核心问题是逻辑条件的逻辑关系搞反了,导致过滤结果完全不符合预期。

原查询的错误分析

你的需求是移除同时满足以下两个条件的记录:

  1. (orig_code, send_id)是('ABCD001','ABCD001')或('ABCDXXX','ABCDXXX')
  2. ref_no以35RE或20PS开头

但原查询的逻辑完全偏离了这个需求:

SELECT * FROM T1 WHERE ((orig_code, send_id) NOT IN ( ('ABCD001', 'ABCD001'), ('ABCDXXX', 'ABCDXXX')) AND (ref_no NOT LIKE '35RE%' OR ref_no NOT LIKE '20PS%'))

这里的关键错误是ref_no NOT LIKE '35RE%' OR ref_no NOT LIKE '20PS%'——任何ref_no都不可能同时以35RE和20PS开头,所以这个OR表达式永远为真。这就导致原查询实际上变成了:只保留(orig_code, send_id)不在指定组的记录,直接排除了所有在指定组的记录(不管它们的ref_no是什么),完全不符合你要保留指定组中合法ref_no记录的需求。

正确的SQL写法

下面提供两种等价的正确写法,都能得到你期望的结果:

写法1:直接排除目标记录(最直观)

用NOT()包裹你要移除的条件组合,逻辑和需求描述完全对应,可读性最强:

SELECT * FROM T1 
WHERE NOT (
    (orig_code, send_id) IN ( ('ABCD001', 'ABCD001'), ('ABCDXXX', 'ABCDXXX') )
    AND (ref_no LIKE '35RE%' OR ref_no LIKE '20PS%')
);

写法2:用德摩根定律转换逻辑(等价)

根据逻辑运算的德摩根定律,NOT (A AND B)等价于NOT A OR NOT B,可以拆成两种需要保留的情况:要么不在指定组,要么在指定组但ref_no既不是35RE开头也不是20PS开头:

SELECT * FROM T1 
WHERE 
    (orig_code, send_id) NOT IN ( ('ABCD001', 'ABCD001'), ('ABCDXXX', 'ABCDXXX') )
    OR (ref_no NOT LIKE '35RE%' AND ref_no NOT LIKE '20PS%');

这两种写法都会返回你想要的结果:

ABCD001 ABCD001 30RE745
ABCDXXX ABCDXXX 55RE741
DBWS001 ABCD001 25PS369
MNKSXXX ABCDXXX 21PS258
ABCD001 ABCD001 25PS369
ABCDXXX ABCDXXX 21PS258

内容的提问来源于stack exchange,提问作者SAMROX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:00:08