【MySQL】嵌套查询—数据之旅:解析层层嵌套的迷思

🎊专栏【MySQL】

🌺每日一句:宝剑锋从磨砺出,梅花香自苦寒来

⭐欢迎并且感谢大家指出我的问题

文章目录

嵌套查询

(1)不相关子查询(带有IN谓词的子查询)

🍔定义

🍔使用说明

🍔特点

🍔实际操作

🍔三层嵌套查询

(2)相关子查询(带有EXISTS谓词的子查询)

🍔定义

🍔使用说明

🍔特点

🍔带有EXISTS的子查询

🍔带多个EXISTS(或NOT EXISTS)查询

🍔带有比较运算符的子查询

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

(3)总结


嵌套查询

定义

        在SQL语言中,一个SELECR-FROM-WHERE语句称为一个查询块,将一个查询块嵌套在另一个查询块的WHERE子句或HAVING语句的条件中的查询称为嵌套查询。

子查询分为不相关子查询和相关子查询

(1)不相关子查询(带有IN谓词的子查询)

🍔定义

   子查询的查询条件不依赖于父查询,这类子查询称为不相关子查询(一般子查询)。

🍔使用说明

1.不相关子查询一般使用谓词IN。

2.由里向外,逐层处理。即每个子查询在上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件。

🍔特点

能独立运行,子查询条件不依赖父查询;

只能运行一次;

先执行子(内)查询

代码如下👇🏻

SELECT sname     /*外查询/父查询*/
FROM student
WHERE sno IN (      /*括号里面的为内查询或子查询*/
SELECT sno
FROM sc
WHERE cno='2');

 运行结果👇🏻

🍔实际操作

例1(查询与刘晨在同一个系学习的学生)

代码如下👇🏻

SELECT sno,sname,sdept
FROM student
WHERE sdept IN
             ( SELECT sdept
               FROM student
               WHERE sname='刘晨');

 运行结果👇🏻

例2(查询有一门课程成绩等于85分的学号和姓名)

代码如下👇🏻

SELECT sno,sname
FROM student
WHERE sno IN(
          SELECT sno
          FROM sc
          WHERE grade=85);

 运行结果👇🏻

🍔三层嵌套查询

例1(查询选修了课程名为"信息系统"的学生学号和姓名)

代码如下👇🏻

SELECT sno,sname
FROM student
WHERE sno IN(
SELECT sno
FROM sc
WHERE cno IN(
SELECT cno
FROM course
WHERE cname='信息系统')
);

 运行结果👇🏻

例2(查询李同学不学的课程的课程名)

代码如下👇🏻

SELECT cname 
FROM course
WHERE cno NOT IN(
 SELECT cno
 FROM sc
 WHERE sno IN (
 SELECT sno 
 FROM student
 WHERE sname LIKE '李%'));

 运行结果👇🏻

(2)相关子查询(带有EXISTS谓词的子查询)

🍔定义

    子查询的查询条件依赖于外层父查询的某个属性值,称这类查询为相关子查询。

🍔使用说明

1.相关子查询一般使用谓词EXISTS。

2.首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果表,然后再取外层表的下一个元组,重复这一过程,直至外层表全部查询完为止。

🍔特点

子查询不能独立运行;

子查询多次运行;

先执行父(外)查询;

🍔带有EXISTS的子查询

EXISTS说明:

带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值'true'或逻辑假值'false'

若内层查询结果非空,则外层的WHERE子句返回真值

若内层查询结果为空,则外层的WHERE子句返回假值

NOT EXISTS说明:

若内层查询结果非空,则外层的WHERE子句返回假值

若内层查询结果为空,则外层的WHERE子句返回真值

注意事项

由EXISTS(或NOT EXISTS)引出的子查询,其目标列表达式通常都用*,因为带EXISTS(或NOT EXISTS)的子查询只返回真值或假值,给出列名无实际意义

(查询有一门课程成绩等于85分的学号和姓名)

代码如下👇🏻

SELECT sno,sname
FROM student
WHERE EXISTS
( SELECT *
 FROM sc
 WHERE student.sno=sc.`Sno` AND grade=85);

 运行结果👇🏻

例2(查询没有选修了二号课程的学生姓名)

代码如下👇🏻

SELECT sname
 FROM student
 WHERE NOT EXISTS(
 SELECT *
 FROM sc
 WHERE sno=student.`Sno` AND cno='2');

 运行结果👇🏻

例3(查询没有与刘晨在同一个系学习的学生)

代码如下👇🏻

SELECT sno,sname,sdept
 FROM student s1
 WHERE NOT EXISTS(
 SELECT *
 FROM student s2
 WHERE s2.`Sdept`=s1.`Sdept` AND s2.`Sname`='刘晨');

 运行结果👇🏻

🍔带多个EXISTS(或NOT EXISTS)查询

例如(查询选修了全部课程的学生姓名)

代码如下👇🏻

SELECT sname
 FROM student 
 WHERE NOT EXISTS(
 SELECT *              /*子查询1*/
 FROM course
 WHERE NOT EXISTS(
 SELECT *              /*子查询2*/
 FROM sc
 WHERE sno=student.`Sno` AND cno=course.`Cno`));

🍔带有比较运算符的子查询

例如(找出每个学生超过他选修课程平均成绩的课程号)

代码如下👇🏻

 SELECT sno,cno
 FROM sc X
 WHERE grade >=(
 SELECT AVG(grade)
 FROM sc Y
 WHERE y.`Sno`=x.`Sno`);

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

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

代码如下👇🏻

SELECT sname,sage
 FROM student
 WHERE sage< ANY(
 SELECT sage
 FROM student
 WHERE sdept='cs')
AND sdept <> 'cs';   /*父查询块中的条件*/

等价于代码如下👇🏻

SELECT sname,sage
 FROM student
 WHERE sage<(
 SELECT MAX(sage)
 FROM student
 WHERE sdept='cs')
 AND sdept <> 'cs';

(3)总结

不同形式的查询间的替换:

1.连接查询一定能用嵌套查询替换

2.所有带IN谓词比较运算符ANY和ALL谓词的子句查询都能用带EXISTS谓词的子查询等价替换

3.一些带EXISTS或NOT EXISTS谓词的子查询不能被其他形式的子查询等价替换

🌺如果大家有不明白的地方,或者文章部分内容有问题,欢迎大家在评论区讨论,指正

  • 66
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 31
    评论
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dawn黎明开始

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值