not exists 和 not in 查询结果不一致的原因

SQL>create table test1(a number);
SQL>create table test2(b varchar2(20));
SQL>insert into test1 select object_id from user_objects;
SQL>insert into test2 select object_id from user_objects;
SQL>update test2 set b = null where b  >70000;

SQL>select count(1) from test1 t1 where not exists
(select 1 from test2 t2 where t1.a=t2.b);

  COUNT(1)
----------
       110

SQL>select count(1) from test1  where a not in
(select b from test2);

  COUNT(1)
----------
         0

      看似相同的语义实质查询的结果不一致,原因是单列的NULL,如果非相关子查询的结果有NULL,那么整个条件为,FALSE/UNKNOWN,也就是没有结果的原因,如果深入分析下,等价于SELECT .... WHERE ID <> NULL AND ID <>....根据NULL的比较和逻辑运算规则,可以知道整个条件要么是false,要么是unknown,所以没有结果。

       多说一句,IN子查询相当于OR条件,根据NULL的逻辑运算规则,哪个条件为TRUE的行就返回那个行。


通过10053事件跟踪得出以上的语句转换

not exists:

SELECT COUNT(*) "COUNT(1)"
  FROM "TEST"."TEST2" "T2", "TEST"."TEST1" "T1"
 WHERE "T1"."A" = TO_NUMBER("T2"."B");
not in:
SELECT COUNT(*) "COUNT(1)"
  FROM "TEST"."TEST1" "SYS_ALIAS_1"
 WHERE NOT EXISTS
 (SELECT /*+ */ 0 FROM "TEST"."TEST2" "TEST2"
         WHERE LNNVL(TO_NUMBER("TEST2"."B") <> "SYS_ALIAS_1"."A"));

注:lnnvl用于某个语句的where子句中的条件,如果条件为true就返回false;如果条件为UNKNOWN或者false就返回true。该函数不能用于复合条件如AND, OR, or BETWEEN中。

根据10053事件可以推导出,如果一定要用not in,可以改写为

SQL> select count(1) from test1
      where a not in (select b from test2 where test1.a=test2.b);
 
  COUNT(1)
----------
       110


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值