SQL 数据查询(4)—— 嵌套查询

SQL 数据查询(4)—— 嵌套查询文章目录嵌套循环SELECTSnameFROMStudentWHERESnoIN( SELECTSno FROMSC WHERECno=’2′);

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

型如下面这样的就是嵌套查询:

SELECT Sname
FROM Student
WHERE Sno IN(
	SELECT Sno
	FROM SC
	WHERE Cno = '2'
);

SELECT语句不能使用ORDER BY子句
ORDER BY只能对最终查询结果排序

带有IN谓词的子查询

IN谓词用于子查询结果是一个集合的情况

例3.55:查询与“刘晨”在同一个系学习的学生

先分步用单表查询做
第一步:

SELECT Sdept
FROM Student
WHERE Sname='刘晨';

在这里插入图片描述

SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept='CS'; /*CS位置添加 上面查询到的系名*/

在这里插入图片描述
所以根据这个原理,我们可以进行一下嵌套查询,将代码合并一下:

SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN(
	SELECT Sdept
	FROM Student
	WHERE Sname='刘晨'--; 
);

在嵌套查询中,IN谓词后面的语句块中,结尾不需要添加分号
并且字符串都是用单引号来引用的,双引号会报错(可能习惯了C语言的问题,这里总是不习惯)
在这里插入图片描述

除此之外,这道例题也可以使用自身连接来查询

SELECT Sno,Sname,Sdept
FROM Student S1,Student S2
WHERE S1.Sdept = S2.Sdept AND S1.Sname = '刘晨'; 

在这里插入图片描述

这里给我报错是因为虽然是自身连接,但是还是要指明要选取的是哪个表格的组

SELECT S1.Sno,S1.Sname,S1.Sdept
FROM Student S1,Student S2
WHERE S1.Sdept = S2.Sdept AND S2.Sname = '刘晨'; 

在这里插入图片描述

例3.56:查询选修了课程名为“信息系统”的学生学号和姓名

SELECT Sno,Sname
FROM Student
WHERE Sno IN(
	SELECT Sno
	FROM SC
	WHERE Cno IN(
		SELECT Cno
		FROM Course
		WHERE Cname = '信息系统'
	)
);

在这里插入图片描述

这道题我感觉上课听的时候感觉好抽象,现在看看其实也不是理解的很透彻

嵌套查询首先要注意的是,从内向外

  1. 先在Course表中找到信息系统的课程号
  2. 再根据课程号,在SC表中找选修了信息课程的学生学号
  3. 最后根据第二步查到的学生学号,在Student表中找到学生的学号和姓名


    嵌套查询有一个特点:就是 WHERE 的条件查询的属性,一定是在内层中要SELECT选择的属性

这道题也可以使用连接查询实现

SELECT Student,Sno,student.Sname
FROM Student,Course,SC
WHERE Student.Sno = Course.Sno AND
		Course.Cno = SC.Cno

带有比较运算符的子查询

常见的比较运算符是>,<,=,>=,<=,!=,<>等。
例3.55中的IN就可以用 = 来实现

SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN(
	SELECT Sdept
	FROM Student
	WHERE Sname='刘晨'--; 
);

例3.57:找出每个学生超过他自己选修课程平均成绩的课程号

SELECT Sno,Cno
FROM SC x
WHERE Grade >= (
	SELECT AVG(Grade)
	FROM SC y
	WHERE y.Sno = x.Sno
);

(相关子查询)查询步骤是:

  1. 从外层查询中选出一个SC的元组的x,将元组x的Sno的值在传到内层查询
  2. 执行内层循环,将得到的值代替内层查询
  3. 执行外层查询

带有ANY(SOME)或ALL谓词的子查询

>ANY	大于子查询结果中的某个值
>ALL	大于子查询结果中的所有值
<ANY	小于子查询结果中的某个值
<ALL	小于子查询结果中的所有值
>=ANY	大于等于子查询结果中的某个值
>=ALL	大于等于子查询结果中的所有值
<=ANY	小于等于子查询结果中的某个值
<=ALL	小于等于子查询结果中的所有值
=ANY	等于子查询结果中的某个值
=ALL	等于子查询结果中的所有值(通常没有实际意义)
!=(或<>) ANY	不等于子查询结果中的某个值
!=(或<>) ANY	不等于子查询结果中的所有值

例3.58:查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄

SELECT Sname,Sage
FROM Student
WHERE Sdept != 'CS' AND Sage < ANY(
	SELECT Sage
	FROM Student
	WHERE Sdept = 'CS'
);

在这里插入图片描述
本题目可以使用聚集函数来实现(先查询出CS系中最大年龄20,再查询出非CS系中年龄小于20岁的学生)

SELECT Sname,Sage
FROM Student
WHERE Sdept != 'CS' AND Sage < (
	SELECT MAX(Sage)
	FROM Student
	WHERE Sdept = 'CS'
);

小于ANY就是小于任何一个值,说明小于哪一个都可以,所以小于MAX就好(上课时候没理解ANY的含义,想的是小于所有值,没整明白,哈哈,英语不太好)

例3.59:查询非计算机科学系中比计算机科学系所有学生年龄小的学生姓名和年龄

SELECT Sname,Sage
FROM Student
WHERE Sdept != 'CS' AND Sage < ALL(
	SELECT Sage
	FROM Student
	WHERE Sdept = 'CS'
);

在这里插入图片描述

我个人觉得不像书上那么写,将所有约束条件写在一起,将有嵌套的查询写在最后,这样更加好理解

SELECT Sname,Sage
FROM Student
WHERE Sdept != 'CS' AND Sage <(
	SELECT Min(Sage)
	FROM Student
	WHERE Sdept = 'CS'
);

事实上,聚集函数实现子查询 通常 比直接用ANY和ALL效率高

带有EXISTS谓词的子查询

EXISTS代表存在量词,带有EXISTS的子查询不返回任何数据,只产生true和false两个值

例3.60:查询所有选修了1号课程的学生姓名

SELECT Sname
FROM Student
WHERE EXISTS(
	SELECT *
	FROM SC
	WHERE Sno = Student.sno AND Cno = '1'
);

在这里插入图片描述

由EXISTS引出的子查询,其目标列表达式通常用 * 表示,因为我们只需要知道他在不在表中即可

例3.61:查询没有选修1号课程的学生姓名

SELECT Sname
FROM Student
WHERE NOT EXISTS(
	SELECT *
	FROM SC
	WHERE Sno = Student.sno AND Cno = '1'
);

在这里插入图片描述

一些带有EXISTS 或 NOT EXISTS谓词的子查询不能被其他形式的子查询等价交换,但所有带IN谓词、比较运算符、ANY、ALL谓词的子查询都能带EXISTS谓词的子查询等价交换

SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN(
	SELECT Sdept
	FROM Student
	WHERE Sname='刘晨'--; 
);

上面这个3.55的例子就可以替换成以下

SELECT Sno,Sname,Sdept
FROM Student S1
WHERE EXISTS(
	SELECT *
	FROM Student S2
	WHERE S2.Sdept = S1.Sdept AND S2.Sname = '刘晨'
);

例3.62:查询选修了全部课程的学生姓名

SQL中不存在全程量词
所以对于任意量词我们可以根据离散数学的知识改写一下
用存在来表示任意

SELECT Sname
FROM Student
WHERE NOT EXISTS(
	SELECT *
	FROM Course
	WHERE NOT EXISTS(
		SELECT *
		FROM SC
		WHERE Sno = Student.Sno AND Cno = Course.Cno
	)
);

选取全部课程的学生 就是 没有课程(Course)不是他没选的(SC)

例3.63:查询至少选修了学生201215122选秀的全部课程的学生号码

SELECT DISTINCT Sno
FROM SC SCX
WHERE NOT EXISTS(
	SELECT *
	FROM SC SCY
	WHERE SCY.Sno = '201215122' AND NOT EXISTS(
		SELECT * 
		FROM SC SCZ
		WHERE SCZ.Sno = SCX.Sno AND SCZ.Cno = SCY.Cno
	)
);

在这里插入图片描述

感觉带有 EXISTS 谓词地方的题目,复杂起来非常难于理解透彻,尽管我已经写好了一遍,但还是感觉很晦涩,这两天我再自己琢磨一下,等我完全领悟了,再把这个地方自己的理解补上来

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/169432.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 字节与bit的关系_bit和byte换算关系

    字节与bit的关系_bit和byte换算关系bit、byte、位、字节、汉字的关系

    2022年4月21日
    78
  • 数据库隔离级别理解「建议收藏」

    数据库隔离级别理解「建议收藏」1.为什么要选择隔离级别?通过例子说明隔离级别的必要性:假设一个场景,一对夫妻共用一个账户,妻子喜欢网上支付,丈夫喜欢刷卡支付。第一类丢失情况:整个过程中只有老公消费1000元,而最后时刻,老婆回滚事务,恢复到了原来的10000元,这不符合实际。这样的两个事务并发,一个提交,一个回滚导致的不一致成为第一类丢失更新,不过大部分数据库(mysql,o…

    2022年5月9日
    38
  • PHP headers_sent() 函数

    PHP headers_sent() 函数

    2021年9月20日
    37
  • springsecurity官网_log4j.properties配置

    springsecurity官网_log4j.properties配置由于项目框架古老spring3.0springsecurity2.0.4,但功能齐全,所以个人想要升级各个jar包版本,以减少不必要的已知bug目标更换为springsecurity4.2springdata换为最新问题1:spring版本不匹配,jar包冲突这个是最好解决的,先把springsecurity做最基础配置,换几个理论上兼容的spring版本试试就行,最终选定…

    2022年5月3日
    52
  • charles乱码怎么解决_charles乱码怎么解决

    charles乱码怎么解决_charles乱码怎么解决前言当使用Charles抓包时,发现数据都是乱码,这时需要安装证书解决办法1.点击charles窗口,点击左上角Help->SSLProxying→InstallCharles

    2022年7月28日
    1
  • Ubuntu18.04安装gcc——史上最全安装教程

    Ubuntu18.04安装gcc——史上最全安装教程心路历程:花了整个周末的时间,最终没有安装好gcc,使用的Linux版本是Ubuntu18.04。但是,历尽千辛万苦,第二天晚上终于搞好!!第一步首先在命令行里面输入pingwww.baidu.com。这一步测试Ubuntu是否有网络,若出现如图2所示的信息,可以跳过第二步进行第三步。第二步设置网络,首先在虚拟器-设置-网络适配器里面选择NAT模式。然后再进行第一步操作,有些同学还是没有网络,先别急,还需继续设置,Win+R输入services.msc调出服务,分别右键VMwareDHCP

    2022年7月24日
    57

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号