Oracle not in查不到应有的结果(NULL、IN、EXISTS详解)

2023-12-11 13:33

本文主要是介绍Oracle not in查不到应有的结果(NULL、IN、EXISTS详解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

语句1:
Select * from  table1 A where A.col1 not in ( select col1 from table2 B )

如果这样,本来应该有一条数据,结果没有。
如果我改写成这样:

语句2:
select * from table1 A where not exists (SELECT * FROM table2 B where B.col1 = A.col1)结果就正确,有一条数据显示。


经过一番搜索,原以为是子查询结果集太大的原因。

后来有网上强人指点:子查询里面有空集。即子查询的结果集里面有NULL的结果。

把查询语句修改成:

语句3:
Select * from  table1 A where A.col1 not in ( select col1 from table2 B where B.col1 is not null )

果然就查出来了。而且一点不差。。。厉害阿~~~


下面是针对本文题的分析:

1。 首先来说说Oracle中的NULL。

Oracle中的NULL代表的是无意义,或者没有值。将NULL和其他的值进行逻辑运算,运算过程中,NULL的表现更象是FALSE。
下面请看真值表:


                AND NULL                                OR NULL
 TRUE        NULL                                         TRUE
 FALSE      FALSE                                       NULL
 NULL        NULL                                          NULL

 

另外,NULL和其他的值进行比较或者算术运算(<、>、=、!=、+、-、*、/),结果仍是NULL。

如果想要判定某个值是否为NULL,可以用IS NULL或者IS NOT NULL。

2. 再来说说Oracle中的IN。

in是一个成员条件, 对于给定的一个集合或者子查询,它会比较每一个成员值。
IN功能上相当于 =ANY 的操作,而NOT IN 功能上相当于 !=ALL 的操作。
IN在逻辑上实际上就是对给定的成员集合或者子查询结果集进行逐条的判定,例如:
SELECT * FROM table1 A WHERE A.col1 in (20,50,NULL);实际上就是执行了
SELECT * FROM table1 A WHERE A.col1=20 OR A.col1=50 OR A.col1=NULL;这样,根据NULL的运算特点和真值表,我们可以看出,上边这个WHERE 字句可以被简化(如果返回NULL则无结果集返回,这一点和FALSE是一样的)为
WHERE A.col1=20 OR A.col1=50也就是说,如果你的table1中真的存在含有NULL值的col1列,则执行该语句,无法查询出那些值为null的记录。

再来看看NOT IN。根据逻辑运算关系,我们知道,NOT (X=Y OR N=M) 等价于 X!=Y AND N!=M,那么:
SELECT * FROM table1 A WHERE A.col1 not in (20,50,NULL)等价于
SELECT * FROM table1 A WHERE A.col1!=20 AND A.col1!=50 AND A.col1!=NULL根据NULL的运算特性和真值表,该语句无论前两个判定条件是否为真,其结果一定是NULL或者FALSE。故绝对没有任何记录可以返回。

这就是为什么语句1查不到应有结果的原因。当然,如果你用NOT IN的时候,预先在子查询里把NULL去掉的话,那就没问题了,例如语句3。
有些童鞋可能要问了:那如果我想把A表里面那些和B表一样col1列的值一样的记录都查出来,即便A、B两表里面的col1列都包括值为NULL的记录的话,用这一条语句就没办法了吗?

我只能很遗憾的告诉你,如果你想在WHERE后面单纯用IN 似乎不太可能了,当然,你可以在外部的查询语句中将NULL条件并列进去,例如:
SELECT * FROM table1 A WHERE A.col1 in (SELECT B.col1 FROM table2 B) OR A.col1 IS NULL;


3. 最后谈谈EXISTS。

有人说EXISTS的性能比IN要好。但这是很片面的。我们来看看EXISTS的执行过程:
select * from t1 where exists ( select * from t2 where t2.col1 = t1.col1 )相当于:
for x in ( select * from t1 )
   loop
      if ( exists ( select * from t2 where t2.col1 = x.col1 )
      then
         OUTPUT THE RECORD in x
      end if
end loop
也就是说,EXISTS语句实际上是通过循环外部查询的结果集,来过滤出符合子查询标准的结果集。于是外部查询的结果集数量对该语句执行性能影响最大,故如果外部查询的结果集数量庞大,用EXISTS语句的性能也不一定就会好很多。

当然,有人说NOT IN是对外部查询和子查询都做了全表扫描,如果有索引的话,还用不上索引,但是NOT EXISTS是做连接查询,所以,如果连接查询的两列都做了索引,性能会有一定的提升。
当然至于实际的查询效率,我想还是具体情况具体分析吧。


那么我们不妨来分析一下语句2为什么能够的到正确的结果吧:

语句2是这样的:
select * from table1 A where not exists (SELECT B.col1 FROM table2 B where B.col1 = A.col1)
实际上是这样的执行过程:

for x in ( select * from table1 A )
   loop
      if (not exists ( select * from table2 B where B.col1 = x.col1 )
      then
         OUTPUT THE RECORD in x
      end if
end loop
由于表A中不包含NULL的记录,所以,遍历完表A,也只能挑出表A中独有的记录。

这就是为什么语句2能够完成语句3的任务的原因。

但如果表A中存在NULL记录而表B中不存在呢?

这个问题请大家自己分析吧。哈哈。有答案了可以给我留言哦。


答案:A表中的NULL也会被查出来。因为select * from table2 B where B.col1 = NULL不返回结果,故
not exists ( select * from table2 B where B.col1 = x.col1 )的值为真。

 

以上SQL运行结果在MySQL和Oracle上都已经通过。

 

原文:http://www.blogjava.net/zhangwei217245/archive/2010/03/01/310708.html,感谢。

这篇关于Oracle not in查不到应有的结果(NULL、IN、EXISTS详解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/480860

相关文章

Spring IOC的三种实现方式详解

《SpringIOC的三种实现方式详解》:本文主要介绍SpringIOC的三种实现方式,在Spring框架中,IOC通过依赖注入来实现,而依赖注入主要有三种实现方式,构造器注入、Setter注入... 目录1. 构造器注入(Cons编程tructor Injection)2. Setter注入(Setter

Java中注解与元数据示例详解

《Java中注解与元数据示例详解》Java注解和元数据是编程中重要的概念,用于描述程序元素的属性和用途,:本文主要介绍Java中注解与元数据的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参... 目录一、引言二、元数据的概念2.1 定义2.2 作用三、Java 注解的基础3.1 注解的定义3.2 内

JavaScript中的isTrusted属性及其应用场景详解

《JavaScript中的isTrusted属性及其应用场景详解》在现代Web开发中,JavaScript是构建交互式应用的核心语言,随着前端技术的不断发展,开发者需要处理越来越多的复杂场景,例如事件... 目录引言一、问题背景二、isTrusted 属性的来源与作用1. isTrusted 的定义2. 为

使用Python实现操作mongodb详解

《使用Python实现操作mongodb详解》这篇文章主要为大家详细介绍了使用Python实现操作mongodb的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、示例二、常用指令三、遇到的问题一、示例from pymongo import MongoClientf

一文详解Python中数据清洗与处理的常用方法

《一文详解Python中数据清洗与处理的常用方法》在数据处理与分析过程中,缺失值、重复值、异常值等问题是常见的挑战,本文总结了多种数据清洗与处理方法,文中的示例代码简洁易懂,有需要的小伙伴可以参考下... 目录缺失值处理重复值处理异常值处理数据类型转换文本清洗数据分组统计数据分箱数据标准化在数据处理与分析过

详解如何在React中执行条件渲染

《详解如何在React中执行条件渲染》在现代Web开发中,React作为一种流行的JavaScript库,为开发者提供了一种高效构建用户界面的方式,条件渲染是React中的一个关键概念,本文将深入探讨... 目录引言什么是条件渲染?基础示例使用逻辑与运算符(&&)使用条件语句列表中的条件渲染总结引言在现代

详解Vue如何使用xlsx库导出Excel文件

《详解Vue如何使用xlsx库导出Excel文件》第三方库xlsx提供了强大的功能来处理Excel文件,它可以简化导出Excel文件这个过程,本文将为大家详细介绍一下它的具体使用,需要的小伙伴可以了解... 目录1. 安装依赖2. 创建vue组件3. 解释代码在Vue.js项目中导出Excel文件,使用第三

SQL注入漏洞扫描之sqlmap详解

《SQL注入漏洞扫描之sqlmap详解》SQLMap是一款自动执行SQL注入的审计工具,支持多种SQL注入技术,包括布尔型盲注、时间型盲注、报错型注入、联合查询注入和堆叠查询注入... 目录what支持类型how---less-1为例1.检测网站是否存在sql注入漏洞的注入点2.列举可用数据库3.列举数据库

Linux之软件包管理器yum详解

《Linux之软件包管理器yum详解》文章介绍了现代类Unix操作系统中软件包管理和包存储库的工作原理,以及如何使用包管理器如yum来安装、更新和卸载软件,文章还介绍了如何配置yum源,更新系统软件包... 目录软件包yumyum语法yum常用命令yum源配置文件介绍更新yum源查看已经安装软件的方法总结软

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI