`

转一篇in和exist的文章

 
阅读更多

select * from A
where id in(select id from B)

以上查询使用了in语句,in()只执行一次,它查出B表中的所有id字段并缓存起来.之后,检查A表的id是否与B表中的id相等,如果相等则将A表的记录加入结果集中,直到遍历完A表的所有记录.
它的查询过程类似于以下过程

List resultSet=[];
Array A=(select * from A);
Array B=(select id from B);

for(int i=0;i<A.length;i++) {
for(int j=0;j<B.length;j++) {
if(A[i].id==B[j].id) {
resultSet.add(A[i]);
break;
}
}
}
return resultSet;

可以看出,当B表数据较大时不适合使用in(),因为它会B表数据全部遍历一次.
如:A表有10000条记录,B表有1000000条记录,那么最多有可能遍历10000*1000000次,效率很差.
再如:A表有10000条记录,B表有100条记录,那么最多有可能遍历10000*100次,遍历次数大大减少,效率大大提升.

结论:in()适合B表比A表数据小的情况

select a.* from A a
where exists(select 1 from B b where a.id=b.id)

以上查询使用了exists语句,exists()会执行A.length次,它并不缓存exists()结果集,因为exists()结果集的内容并不重要,重要的是结果集中是否有记录,如果有则返回true,没有则返回false.
它的查询过程类似于以下过程

List resultSet=[];
Array A=(select * from A)

for(int i=0;i<A.length;i++) {
if(exists(A[i].id) { //执行select 1 from B b where b.id=a.id是否有记录返回
resultSet.add(A[i]);
}
}
return resultSet;

当B表比A表数据大时适合使用exists(),因为它没有那么遍历操作,只需要再执行一次查询就行.
如:A表有10000条记录,B表有1000000条记录,那么exists()会执行10000次去判断A表中的id是否与B表中的id相等.
如:A表有10000条记录,B表有100000000条记录,那么exists()还是执行10000次,因为它只执行A.length次,可见B表数据越多,越适合exists()发挥效果.
再如:A表有10000条记录,B表有100条记录,那么exists()还是执行10000次,还不如使用in()遍历10000*100次,因为in()是在内存里遍历比较,而exists()需要查询数据库,我们都知道查询数据库所消耗的性能更高,而内存比较很快.

结论:exists()适合B表比A表数据大的情况

当A表数据与B表数据一样大时,in与exists效率差不多,可任选一个使用.

比如在Northwind数据库中有一个查询为
SELECT c.CustomerId,CompanyName FROM Customers c
WHERE EXISTS(
SELECT OrderID FROM Orders o WHERE o.CustomerID=c.CustomerID)
这里面的EXISTS是如何运作呢?子查询返回的是OrderId字段,可是外面的查询要找的是CustomerID和CompanyName字段,这两个字段肯定不在OrderID里面啊,这是如何匹配的呢?

EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False
EXISTS 指定一个子查询,检测 行 的存在。

语法: EXISTS subquery
参数: subquery 是一个受限的 SELECT 语句 (不允许有 COMPUTE 子句和 INTO 关键字)。
结果类型: Boolean 如果子查询包含行,则返回 TRUE ,否则返回 FLASE 。


例表A:TableIn 例表B:TableEx

(一). 在子查询中使用 NULL 仍然返回结果集
select * from TableIn where exists(select null)
等同于: select * from TableIn

(二). 比较使用 EXISTS 和 IN 的查询。注意两个查询返回相同的结果。
select * from TableIn where exists(select BID from TableEx where BNAME=TableIn.ANAME)
select * from TableIn where ANAME in(select BNAME from TableEx)

(三). 比较使用 EXISTS 和 = ANY 的查询。注意两个查询返回相同的结果。
select * from TableIn where exists(select BID from TableEx where BNAME=TableIn.ANAME)
select * from TableIn where ANAME=ANY(select BNAME from TableEx)

NOT EXISTS 的作用与 EXISTS 正好相反。如果子查询没有返回行,则满足了 NOT EXISTS 中的 WHERE 子句。

结论:
EXISTS(包括 NOT EXISTS )子句的返回值是一个BOOL值。 EXISTS内部有一个子查询语句(SELECT ... FROM...), 我将其称为EXIST的内查询语句。其内查询语句返回一个结果集。 EXISTS子句根据其内查询语句的结果集空或者非空,返回一个布尔值。

一种通俗的可以理解为:将外查询表的每一行,代入内查询作为检验,如果内查询返回的结果取非空值,则EXISTS子句返回TRUE,这一行行可作为外查询的结果行,否则不能作为结果。

分析器会先看语句的第一个词,当它发现第一个词是SELECT关键字的时候,它会跳到FROM关键字,然后通过FROM关键字找到表名并把表装入内存。接着是找WHERE关键字,如果找不到则返回到SELECT找字段解析,如果找到WHERE,则分析其中的条件,完成后再回到SELECT分析字段。最后形成一张我们要的虚表。
WHERE关键字后面的是条件表达式。条件表达式计算完成后,会有一个返回值,即非0或0,非0即为真(true),0即为假(false)。同理WHERE后面的条件也有一个返回值,真或假,来确定接下来执不执行SELECT。
分析器先找到关键字SELECT,然后跳到FROM关键字将STUDENT表导入内存,并通过指针找到第一条记录,接着找到WHERE关键字计算它的条件表达式,如果为真那么把这条记录装到一个虚表当中,指针再指向下一条记录。如果为假那么指针直接指向下一条记录,而不进行其它操作。一直检索完整个表,并把检索出来的虚拟表返回给用户。EXISTS是条件表达式的一部分,它也有一个返回值(true或false)。

在插入记录前,需要检查这条记录是否已经存在,只有当记录不存在时才执行插入操作,可以通过使用 EXISTS 条件句防止插入重复记录。
INSERT INTO TableIn (ANAME,ASEX)
SELECT top 1 '张三', '男' FROM TableIn
WHERE not exists (select * from TableIn where TableIn.AID = 7)

EXISTS与IN的使用效率的问题,通常情况下采用exists要比in效率高,因为IN不走索引,但要看实际情况具体使用:
IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。


分享到:
评论

相关推荐

    Administration of Veritas NetBackup Appliances(VCS-279)考题.docx

    在这篇文章中,我们将详细解释Veritas NetBackup Appliances的管理,包括NetBackup的基本概念、备份和还原、存储单元、证书撤销列表、网络连接测试等方面的知识点。 NetBackup基本概念 NetBackup是一种数据备份和...

    Vibration Transfer Path Analysis and Path Ranking for NVH

    一篇有关车内振动传递路径分析的文章。英文摘要:By new advancements in vehicle manufacturing, evaluation of vehicle quality assurance has got a more critical issue. Today noise and vibration generated ...

    commons-logging-1.2.1.1.jar

    在本篇文章中,我们将深入探讨Commons Logging的核心功能、使用方法以及其在实际项目中的应用。 首先,我们来看"commons-logging-1.2.1.1.jar"这个文件,它是Commons Logging的一个具体版本。1.2.1.1是该库的一个...

    exists SQL用法详解、exists和not exists的常用示例

    本篇文章将详细介绍这两个关键字的用法,并通过实例进行解析。 首先,`EXISTS`的语法是:主查询中的条件是`EXISTS (子查询)`,如果子查询返回任何行(即使只有一行或零行),那么`EXISTS`为真,整个查询继续执行。...

    MySQL面试题经典40问!(全).docx

    有关Mysql之前有单独写过几篇文章•一文详解脏读、不可重复读、幻读•一文详解MySQL的锁机制•手把手教你分析解决MySQL死锁问题•看一遍就懂:MVCC原理详解•MySQL索引经典15问!之所以单独写,是因为这几块内容比较...

    python去重,一个由dict组成的list的去重示例

    本篇文章将详细介绍如何对一个由字典(dict)组成的列表(list)进行去重操作,并通过几个具体的例子来展示不同的实现方式。 #### 背景介绍 假设我们有一个列表,其中的每个元素都是一个字典。我们需要根据某个...

    广东署山市顺德区均安中学高中英语Unit14CareersLesson32导学案无答案北师大版必修5

    最后,学生需要运用所学内容撰写一篇记叙文,这有助于巩固新学的词汇和表达方式,同时锻炼写作技能。 总的来说,这个导学案是一个综合性的学习工具,涵盖了词汇学习、阅读策略训练和应用实践,旨在全面提高学生的...

    基于Python实现用户管理系统

    本篇文章将详细介绍如何使用Python语言来构建一个简单的用户管理系统。 #### 一、项目背景与目标 随着互联网应用的普及和发展,越来越多的应用程序需要具备用户注册、登录的功能。这些功能不仅能够提高用户体验,...

    windows 批处理笔记

    这篇博客文章可能是作者分享的一些关于批处理的实用技巧和经验。 `tomcatInstall.bat`文件名暗示这是一个用于安装Tomcat服务器的批处理脚本。Tomcat是Apache软件基金会的一个开源项目,是一个流行的Java应用服务器...

    MATLAB主要函数指令表(功能) (2).pdf

    本篇文章将深入解析MATLAB的主要函数指令,帮助用户更好地理解和运用这些工具。 首先,MATLAB 提供了丰富的信息查询和工作空间管理指令。`help` 可以获取关于任何函数或命令的帮助信息,`helpbrowser` 和 `helpdesk...

    对txt文件批量处理

    本篇文章将基于提供的标题“对txt文件批量处理”、描述“对txt文件批量添加文字”以及标签“批量替换”,结合给出的部分内容,深入探讨如何利用批处理脚本来实现对TXT文件的批量操作,并详细介绍其中涉及的关键技术...

    python实现数独算法实例

    本篇文章将详细介绍如何使用Python来实现数独算法,并通过具体的代码实例来帮助读者更好地理解和掌握这一算法。 #### 二、数独算法的基本原理 数独问题本质上是一个约束满足问题(CSP),可以通过回溯法等算法来解决...

    python批量下载ECMWF数据的代码

    本篇文章将详细讲解如何利用Python批量下载ECMWF(欧洲中期天气预报中心)的数据。 ECMWF是全球领先的气象预报机构之一,提供了大量的气候和天气预报数据。为了方便用户访问这些数据,他们提供了API(应用程序接口...

    02_paramAPI访问1

    本篇文章将深入探讨如何在Python中使用`rospy`库来操作`Param`数据。 首先,`Param API` 提供了获取和设置ROS参数的功能。在ROS中,参数可以存储在服务器上,然后被不同的节点共享和使用。这使得配置信息可以在整个...

    大牛总结 MySql常见错误集锦

    本篇文章将深入探讨由大牛总结的MySQL常见错误,并提供解决策略。 1. 错误1045: Access denied for user 'username'@'localhost' (using password: YES/NO) 这个错误通常表示用户名或密码不正确,或者是用户没有...

    图之邻接表详解(C语言版).rar

    本篇文章将详细解析邻接表的概念,以及如何用C语言来实现。 邻接表是图的链式存储结构,它为图中的每个顶点维护一个链表,链表中的元素表示与该顶点相连的所有边。相比于邻接矩阵,邻接表在处理稀疏图(边的数量远...

    2021届高考英语二轮创新练习考前提分必刷题七含解析20210305286

    此外,文件还可能包含一篇阅读理解文章,虽然具体内容未给出,但通常这类练习会涵盖各种题材,如科普、文化、历史等,旨在提高学生的阅读理解能力。 通过这些练习,考生可以系统地复习和巩固英语基础知识,提高应试...

    Windows常用的38个DOS命令

    本篇文章将详细讲解38个常用的DOS命令,帮助你更好地理解和运用这些命令。 1. **CD/CHDIR**: 更改当前目录,例如`cd C:\Users`,可以让你进入指定的文件夹路径。 2. **MD/MKDIR**: 创建新目录,如`md NewFolder`会...

    如何实用snmp来监控linux服务器

    ### 如何实用SNMP来监控Linux服务器 #### 一、SNMP简介与原理 简单网络管理协议(Simple Network Management Protocol, SNMP)是一种广泛应用于互联网上的...希望本篇文章能够帮助读者更好地理解和应用SNMP监控技术。

Global site tag (gtag.js) - Google Analytics