当前位置: 首页 > news >正文

sql中in、exists和not exists的用法


前言

在做数据库实验涉及相关子查询题目中使用exists 和not exists 遇到的问题,还有exists和in 什么时候能替换的问题


一、exists和not exists

相关子查询是相对于简单查询和连接查询是属于复杂的查询,子查询的查询条件依赖父查询(依赖于共同属性,就是外码)。这类查询针对于exists和not exists 的嵌套查询。
存在量词exists大量使用在相关子查询中,sql语言不支持全称量词,所以我们用not exists 实现。在带有exists运算符的嵌套查询中,子查询只返回结果,不返回数据,如果有结果则父查询的where子句为真,否则为假。使用格式如下:

[not]exists (<子查询>)

二、实验例题

1.查询至少选修了学生为140005的学生所选修的全部课程的学生学号的姓名

代码如下(示例):

select sname                             
from student
where not exists(select *   --选出学号为“140005”的学生选择的课程           from SC as SC1where sno='140005'and not exists (select *     --选出学号为“140005”的学生选择的课程    from SC as SC2where SC2.cno=SC1.cno and SC2.sno= student.sno))

因为不能使用全称量词,所以问题转化为查询没有一门课(被学号“140005”的学生选择的课)没有被该生选择的学生的姓名。
嵌套两个查询,父查询第一个select就是从student表里找出sname,第二个select从sc1表里选出学号为“140005”的学生选择的课程,第三个select从是从sc2表中选出课程被该生选择的记录.
在第三个select的where子句中的SC2.sno=student.sno这句就是相关子查询的一个标志,我是这样觉得,子查询和父查询依赖于共同属性(SC2和student的共同属性sno)

2.查询全是男同学选修的课程号

代码如下(示例):

GO                  
select distinct cno    --方法一
from SC
where cno not in (select cnofrom student, SC where  sc.sno = student.sno and ssex = '女' )
GO
select  distinct cno    --方法二
from SC a
where not exists (select *from student,SC bwhere  b.sno=student.sno and ssex='女'and a.cno=b.cno)
GO
select distinct cno    --方法三(就是方法二的复杂化)
from SC a
where not exists (select *from studentwhere ssex='女' and  exists(select *from SC bwhere student.sno=b.sno and a.cno=b.cno))GO
select cno             --方法四 不使用distinct
from Course 
where cno in (select cnofrom SC awhere cno not in (select cno from student,SC bwhere ssex = '女' and b.sno = student.sno))

问题转化:没有一个女生选该课程 ,使用了四种方法,方法一使用IN运算符,方法二使用not exists运算符,最后一种是从Course表中查询,没有重复元组,不使用distinct。关于IN和exists的使用在下面说明。

三、in和exists

1.两种方式实现

in:in运算符是将内表和外表连接起来,先查询内表,再把内表结果与外表匹配,即等值连接,使用in时,where子句中可以指定多个值,即查询字段是否在这多个值中。
exists:exists运算符是检查子查询表中是否有结果,只返回true,false,null,所以查询目标列用“*”表示,不需要指明列名。
题目:
查询选修了“c1”课程但没有选修“c2”课程的学生学号

使用in方式实现

select sno as 学号
from  Course A
where A.cno = 'C1' and  sno not in (select  snofrom  Course Bwhere  cno ='C2' )

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

使用exists方式实现

select sno as 学号
from  Course A
where A.cno = 'C1' and  not exists (select * from Course Bwhere A.sno=B.sno  and  cno ='C2' )

子查询的查询条件依赖父查询,就有A.sno=B.sno,通过子查询(为一个完整的语句)返回的数据是否为null,如果不为null,就会将当前的数据加入结果集,因此我们select * from Course A的时候,我们是从第一条数据开始执行的,每次执行都会去执行exists的子查询.

2.in和exists区别

in()的使用

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

以上查询使用了in语句,in()只执行一次,它查出B表中的所有id字段并缓存起来.之后,检查A表的id是否与B表中的id相等,如果相等则将A表的记录加入结果集中,直到遍历完A表的所有记录.当B表数据较大时不适合使用in(),因为它会B表数据全部遍历一次.
exists()的使用

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

以上查询使用了exists语句,比in()在where子句后面多了一句a.id=b.id,子查询依赖于父查询的共同属性,exists()会执行A.length次,它并不缓存exists()结果集,看结果集中是否有记录,如果有则返回true,没有则返回false.当B表比A表数据大时适合使用exists(),因为它没有遍历操作,只需要再执行一次查询就行
如:A表有100条记录,B表有100000000条记录,那么exists()还是执行100次,因为它只执行A.length次,可见B表数据越多,越适合exists()发挥效果.

3.结论

in()适合B表比A表数据小的情况
exists()适合B表比A表数据大的情况
当A表数据与B表数据一样大时,in与exists效率差不多,可任选一个使用.

http://www.xdnf.cn/news/821179.html

相关文章:

  • 基于PHP的编程类MOOC网站设计与实现
  • MSSQL数据库的安装与使用
  • C++程序正向编译逆向反编译(一)
  • FPGA学习——触发器(FF)
  • MySQL数据库优化(基于酒店2000w条数据)
  • 3dmax vray如何创建真实的灯光?3dmax vray 室内照明教程
  • 番茄花园 Windows XP Pro SP2 美化版 V 6.2
  • LCD1602中文资料
  • java关键字abstract(抽象)详解
  • Android中layout过程详解
  • 网络 || 科来网络分析系统
  • 0磁道损坏的硬盘如何修复?
  • 分享70个Java源码总有一个是你想要的
  • Linux的安装与配置(保姆级教学)
  • Servlet--HttpServletRequest获取请求信息(请求头、请求行、参数)详解
  • Linux网络命令详解
  • 05 ORM
  • 天龙八部单机版(兽血沸腾):大背包天机华裳格武道二
  • root权限获取排行榜,root权限软件排行榜
  • 电子产品硬件开发流程
  • update set命令用来修改表中的数据
  • DataFormatString,DataTextFormatString
  • php钓鱼网站怎么做视频教程,反黑钓鱼网站全过程
  • 5款常用的漏洞扫描工具,网安人员不能错过!
  • 原码反码补码
  • Android开发之修改系统开机Logo与开机动画
  • Windows 7 杜比软件安装
  • 如何快速搭建网站(小白教程)(48小时内完成)
  • 【广工考试笔记】计算机网络考试速成笔记
  • 搜索引擎工作原理