前言

sql的嵌套查询可以说是sql语句中比较复杂的一部分,但是掌握好了的话就可以提高查询效率。下面将介绍带in的子查询、带比较运算符的子查询、带any/all的子查询、带exists的子查询以及基于派生表的子查询。很多数据库是不区分关键字大小写的,并且关键字还会有高亮,所以我为了写语句方便(不要频繁切换大小写或者按shift键)和看着方便(大写一般还要在大脑中转换下)关键字是使用小写。

什么是SQL嵌套查询

嵌套查询指的是一个查询语块可以嵌套在另外一个查询语句块的where子句或者having子句中,前者为子查询或内查询,后者为父查询或外查询。

表的定义

例子使用的表的定义为:

create table `student`(

`sno` char(12) collate utf8_bin not null primary key comment '学号',

`sname` char(30) collate utf8_bin not null comment '姓名',

`birthday` Date collate utf8_bin comment '出生日期'

)engine=InnoDB default charset=utf8 collate=utf8_bin comment '学号信息表';

create table `course`

(

`cno` char(4) collate utf8_bin not null primary key comment '课程号',

`cname` char(40) collate utf8_bin not null comment '课程名',

`ceredit` smallint not null default 0 comment '学分'

)engine=InnoDB default charset=utf8 collate=utf8_bin comment '课程表';

create table `sc`

(

`sno` char(12) collate utf8_bin not null comment '学号',

`cno` char(4) collate utf8_bin not null comment '课程号',

`score` smallint not null default 0 comment '成绩'

)engine=InnoDB default charset=utf8 collate=utf8_bin comment '学生课程表';

#为sc表添加主键和外键

alter table `sc` add primary key (`sno`,`cno`);

alter table `sc` add foreign key(`sno`) references `student`(`sno`);

alter table `sc` add foreign key(`cno`) references `course`(`cno`);

带in的子查询

in关键字主要用于判断表达式是否在多值列表中。返回在多值列表中的记录。

#列出选修了C001课程的学生的学号、姓名

select sno, sname

from student

where sno in (select sno from sc where cno='C001');

这里子查询里面没有依赖父查询,此种查询也叫做不相关子查询。

若子查询条件依赖于父查询,则为相关子查询。

带比较运算符的子查询

带比较运算符的子查询指父查询与子查询之间通过比较运算符连接,并且子查询返回的是单值,才可以用 = 、、 != 、>=、 <=等比较运算符连接。

#选出学号为2016110129的同学所选课程中的成绩大于他平均成绩的课程的课程号

select cno from sc as x

where score >

(

select avg(score) from sc as y where x.sno=y.sno and x.sno = '2016110129'

)

and sno = '2016110129';

这个子查询依赖于父查询,属于相关子查询。

因为这里将同一张表既作为父查询的表又作为子查询的表,所以将这张表取了两个别名,以便区分。

【查询过程】:将父查询中的sno代入子查询中sno进行匹配,然后判断该记录中的课程成绩是否大于该学生的平均成绩,符合条件则返回该记录,否则继续在子查询中匹配该学生的下一条记录。

带any(some)或all的子查询

子查询返回单值时的比较,可以用上面的比较运算符,当返回多值时需要比较,就要使用any(some)或者all。

若是在与多值序列的比较中,只需要满足与多值序列中的一个值满足比较关系就返回true,则用any(some)。

若是在与多值序列的比较中,需要满足与多值序列中的全部值满足比较关系才返回true,则用all。

#查询选课人数最多的课程号

select cno from sc

group by cno

having COUNT(*) >= all(select COUNT(*) from sc group by cno);

【查询过程】:将sc表中的记录按照cno进行分组,筛选记录数最多的课程号。

all(select COUNT(*) from sc group by cno)

是找出所有以cno分组的记录数,是一个多值集合。使用>=也就是选出最大的值。

带exists的子查询

exists代表存在量词,带有EXISTS的子查询不返回任何数据,只产生逻辑真值“true”或者逻辑假值“false”。

使用exists的嵌套语句,若子查询结果不为空,则exists返回true,否则返回false。

使用exists引出的子查询,其目标表达式列都使用*,因为带exists的子查询只返回真值或假值,给出列名无实际含义。

#列出选修了C001课程的学生的学号、姓名

select sno,sname from student

where exists(

select * from sc where sc.sno=student.sno and cno='C001'

);

【查询过程】:从student的第一条记录开始查询,将第一条记录代入子查询中,在sc表中匹配该学生选课记录,若匹配到则立刻返回真,父查询中输出该记录;若匹配完后结果仍为空,否则返回假,继续父查询继续代入下一条记录到子查询中查询。

与in子查询的区别:

在带in的子查询中,会遍历sc表中所有记录进行筛选,带exists的查询找到一条记录就返回,不会遍历整个表,所以带EXISTS的查询是一个优质查询。

附加一题作为exists的练习

“查询选了所有课程的学生”

这里需要使用双层带not exists(即不存在)关键词的查询。具体查询语句如下:

#查询选了所有课程的学生

select sno,sname from student where not exists(

select * from course where not exists (

select * from sc where sc.sno=student.sno and sc.cno=course.cno

)

);

这个相当于一个进行一个双重循环,因为是选出学生的信息,所以student表作为“外层循环”,course表作为“内循环”,在sc表中查询学生的选课记录是否存在。

把student表中第一个学生代入“内循环”,然后开始,在sc表中查询该学生是否选了course表中所有课程。

如果遍历了course表后,不存在没有被选的课程(课程在sc表中没有记录),则说明该学生选了所有课程,内部not exists就会返回假,外部not exists返回为真,说明该学生不存在没有选的课程,外部查询输出该学生的信息,然后开始下一个学生的查询。

在遍历course表时,若有一个课程没有被选,则内部就会立刻返回真(不会继续看下一门课程是否被选),外部查询返回为假,说明该学生没有选完所有课程,外部查询就会开始下一个学生的查询。

再附加一个练习

“找出被所有学生选了的课程的课程号和课程名”

select cno,cname from course where not exists(

select * from student where not exists (

select * from sc where sc.sno=student.sno and sc.cno=course.cno

)

);

基于派生表的查询

select 查询的结果也是一张表,可以作为出现在from子句后面作为派生表进行查询。

#求学分获得8分以上学生的学号 平均分 以及总学分

#需要注意此处的作用域不同,只有该课程的成绩大于60才会获得该课程的学分,平均分包括了所有课程(不及格和及格)

#思路:先将查询到的总学分结果看做是一张表 再与sc表连接进行查询平均分

select sc.sno,total_cre,avg(score) from

(select sno,SUM(ceredit) as total_cre from sc,course where sc.cno=course.cno

and score >= 60

group by sno

having SUM(ceredit) >= 8) as temptable, sc

where temptable.sno=sc.sno

group by sc.sno,sum_cre;

小结

回顾了学习数据库时的嵌套查询,简单总结了一番。当时觉得其中比较难理解的exists查询,现在梳理了一下理解起来也没有那么困难。sql语句还是要常写,不然一些逻辑复杂点的语句就会理解不到。

sql镶嵌查询_【SQL】嵌套查询与子查询相关推荐

  1. from server sql 拼接统计两个子查询_[SQL SERVER系列]之嵌套子查询和相关子查询

    子查询有两种类型,一种是只返回一个单值的子查询,这时它可以用在一个单值可以使用的地方,这时子查询可以看作是一个拥有返回值的函数:另外一种是返回一列值的子查询,这时子查询可以看作是一个在内存中临时存在的 ...

  2. SQL 必知必会·笔记9使用子查询

    子查询(subquery),即嵌套在其他查询中的查询. 1. 利用子查询进行过滤 SELECT 语句中,子查询总是从内向外处理.示例: 1 SELECT cust_name, cust_contact ...

  3. 《SQL必知必会》 11 使用子查询

    利用子查询进行过滤 子查询:嵌套在其他查询中的查询 SELECT cust_id FROM Orders WHERE order_num IN (SELECT order_numFROM OrderI ...

  4. t - sql的阶梯:超越基础水平2:写子查询

    t - sql的阶梯:超越基础水平2:写子查询 原文链接:http://www.sqlservercentral.com/articles/Stairway+Series/104517/ 通过格雷戈里 ...

  5. SQL Server调优系列基础篇(子查询运算总结)

    前言 前面我们的几篇文章介绍了一系列关于运算符的介绍,以及各个运算符的优化方式和技巧.其中涵盖:查看执行计划的方式.几种数据集常用的连接方式.联合运算符方式.并行运算符等一系列的我们常见的运算符.有兴 ...

  6. mybatis 一对多查询 按结果嵌套处理、按查询嵌套处理,以及两者之间的区别

    mybatis 一对多查询 按结果嵌套处理.按查询嵌套处理 最近用到一对多查询,记录一下 实体类 public class RegionEntity implements Serializable { ...

  7. MySQL子查询的优缺点_浅谈mysql的子查询

    浅谈mysql的子查询 mysql的子查询的优化一直不是很友好,一直有受业界批评比较多,也是我在sql优化中遇到过最多的问题之一,你可以点击这里 ,这里来获得一些信息,mysql在处理子查询的时候,会 ...

  8. 嵌套套娃,MySQL子查询,单行与多行子查询,相关和不相关(关联)子查询,完整详细可收藏

    文章目录 1.需求分析与问题解决 2.单行子查询 3.多行子查询 4.相关子查询 5.抛一个思考题 子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从MySQL 4.1开始引入.SQL 中 ...

  9. MySQL 表的增删改查(进阶篇②)· 联合查询 内连接 外连接 · 自连接 · 子查询 exists · 合并查询 union

    接进阶篇①,我们继续学习. 一.联合查询 1.1 内连接 1.2 外连接 1.3 内连接和左右外连接的区别 二.自连接 三.子查询 3.1 单行子查询 3.2 多行子查询 使用 in 范围匹配多行 另 ...

  10. oracle的子查询分几种方法,oracle 子查询的几个种类

    1.where型子查询: select cat_id,good_id,good_name from goods where good_id in (selctmax(good_id)from good ...

最新文章

  1. idea中如何打开RunDashboard窗口,微服务最实用设置
  2. 如何通过Gradle上传Android库到JCenter
  3. dirver时区_JDBD连接MySQL中的驱动与时区问题
  4. body中的font属性和color属性
  5. 如何学习Python课程
  6. @RequestBody注解分析
  7. PHP传引用/作用域 问题
  8. ASP.NET Core 开发-中间件(Middleware)
  9. 通过串口来控制网管型交换机的操作步骤详解
  10. java map isempty_Java HashMap isEmpty() 使用方法及示例
  11. r语言ggplot画两条曲线_R语言作图——Line plot with error
  12. 【2015.9.1】微信开放平台
  13. 软件生命周期、面向对象基本概要
  14. 梦笔记2021-03-05
  15. GPS Programming Tips for Windows Mobile
  16. 安装Pillow指定版本出错
  17. python实现多接口翻译软件
  18. 怎么把电脑上的文件备份到百度网盘?
  19. 微信公众平台开发及优势
  20. 优秀课程案例:使用Scratch制作扫雷插旗排雷完整版

热门文章

  1. 你和“Excel高手”之间,只差一款神级电子表格
  2. 动画演示:Excel中批量生成标签,也可以生成送货单、成绩通知单
  3. Qml 的“Cannot assign to no-existent property “错误。
  4. pycharm中python调用百度aip所遇问题解决方案记录:pip安装时版本报错以及aip导入时报错no module named aip/requests)
  5. GitHub神隐藏功能 强推推推推!!
  6. 数据泵导出导入物化视图(ORA-39083)
  7. java开发面试自我介绍模板_(自我介绍范文)java面试自我介绍
  8. 叮当守护-免Root虚拟位置保护软件,建议收藏
  9. 【Deep Learning】Squeeze-and-Excitation Networks(SENet-2017年ImageNet冠军)
  10. Vmware 复制虚拟机后修改主机名和IP(CentOS7修改主机名和IP)