【MySQL数据库】 (篇三)让你冲刺难点——嵌入查询篇

发布于:2024-04-19 ⋅ 阅读:(35) ⋅ 点赞:(0)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本文章为新手制作🙏,仅用于冲刺突击,大佬路过请指点
本文章为新手制作🙏,仅用于冲刺突击,大佬路过请指点
本文章为新手制作🙏,仅用于冲刺突击,大佬路过请指点

上一篇博客,我们介绍了如何查表,以及对查询操作(条件、排序、去重、连接)📚

本篇我们讲解上机难点,也是水平测试的难点——嵌套🔍

既然是难点,必然会有点绕,对于初学者来说;我们先理解概念,才能运用 进行做题

🎓🎓🎓请大家务必理解下面的概念,概念是基础,基础不牢地动山摇❗

不要自己看着语句的英文单词,想当然!!!


提示:以下是本篇文章正文内容,下面案例可供参考

一、嵌套查询是什么?

嵌套查询是一种在一个查询中嵌套另一个查询的方法。

嵌套查询的逻辑是很关键的,你需要理解内部查询和外部查询之间的关系,以及它们是如何相互作用的。内部查询的结果会作为外部查询的条件数据来源

🧠也就是说根据内部查询的结果来执行外部查询,因此理解这种嵌套关系对于正确编写查询语句至关重要。

嵌套查询在SQL中通常使用子查询的形式。子查询是包含在主查询中的查询,它可以用来执行过滤、检索特定数据或计算聚合值。

在使用嵌套查询时,有几个重要的概念需要理解:

1.内部查询和外部查询:

内部查询是嵌套在主查询内部的查询,而外部查询包围内部查询的主查询。
内部查询首先执行,然后将其结果传递给外部查询, 🎨外部查询使用内部查询的结果进行进一步的处理


2.关联子查询和非关联子查询:

关联子查询依赖于外部查询的结果,而非关联子查询 独立于外部查询而存在。

关联子查询通常在 WHERE 子句中使用,而非关联子查询可以在 SELECT 子句、FROM 子句或 WHERE 子句中使用。


3.子查询的位置:

子查询可以出现在 SELECT 语句、FROM 语句、WHERE 语句HAVING 语句中。它们的位置决定了它们执行的时间和它们所影响的数据范围


4.子查询的返回值:

子查询可以返回单个值、单行值、多行值或表格。根据查询的类型和需求,子查询的返回值可以作为条件、数据源计算结果主查询中使用


二、嵌套查询语句

1.IN操作符:

IN 操作符用于判断某个值 是否在子查询返回的结果集中。它通常用于 WHERE 子句中,语法形式为 value IN (subquery),其中 subquery 是一个返回单列结果集子查询。如果 value 存在于子查询返回的结果集中,则条件为真,否则为假。

示例:

SQL语句:

SELECT *
FROM table_name
WHERE column_name IN (SELECT column_name FROM another_table WHERE condition);

逻辑:
主查询——从表中检索所有行,其中指定的列值包含在子查询的结果集中。
子查询返回的结果集是根据另一个表格的特定条件生成的,如果主查询中的值与子查询的结果匹配,则返回该行。(🧠这就是条件里面套条件,子查询里套子查询——嵌套


2.EXISTS 操作符:

EXISTS 操作符用于检查子查询是否返回任何行
如果子查询返回至少一行结果,则 EXISTS 条件为,否则为假。
通常用于 WHERE 子句中作为条件判断,语法形式为 EXISTS (subquery)

示例:

SQL语句:

SELECT *
FROM table_name
WHERE EXISTS (SELECT column_name FROM another_table WHERE condition);

逻辑:
主查询——从表中检索所有行,并且
子查询——被用作 WHERE 子句中的条件。如果子查询返回至少一行结果,主查询中的条件为真,则返回该行


3.双 NOT EXISTS 操作符:

双 NOT EXISTS 操作符是嵌套查询中的一种复杂条件,用于判断两个子查询之间的关系

内部的 NOT EXISTS 子查询中的条件不成立时,
外部的 NOT EXISTS 子查询才会返回结果

这种结构通常用于检查两个数据集之间的差异或缺失关系。

示例:

SQL语句:

SELECT *
FROM table_name
WHERE NOT EXISTS (
    SELECT column_name FROM table1
    WHERE condition1
)
AND NOT EXISTS (
    SELECT column_name FROM table2
    WHERE condition2
);

逻辑:
主查询——从表中检索所有行,并且
子查询——两个 NOT EXISTS 子查询都被用作 WHERE 子句中的条件

如果两个子查询都不返回结果,即存在满足内部条件的行,
主查询中的条件为真,则返回该行


三、项目实战

表结构如下:
学生(学号,姓名,年龄,性别,所在系)
课程(课程号,课程名,先行课)
选课(学号,课程号,成绩)

题目:查询选修了全部课程的学生的姓名

项目方案分析:

1、明确目标——选修、课程、学生、姓名(其实就是找关键词
2、清楚联系——

  • 首先,我们需要确定有哪些课程存在于课程表中。(我在哪🧠)
  • 然后,我们将检查每个学生是否选修了所有这些课程。(要干嘛🧠)
  • 最后,我们将找到选修了所有这些课程的学生,并检索他们的姓名。(大排查🧠)

3、逻辑中,有两次检查🔍,并且没有指名道姓(特定条件🔍)
——那么,我们就不能直接查找,我们就间接查找——找反例反例的反面就是题目要求
我们将使用双 WHERE NOT EXISTS 子查询来实现这个目标。

  • 首先,我们需要在内部查询中检查每个学生是否存在至少一个课程没有选修
    ————————(🧠也就是检查不符合题目条件的学生)
  • 然后在外部查询检查是否不存在这样的学生
    ————————(🧠也就是求不合题的学生的“补集”——即“符合题目条件的学生”)
  • 这就是双 WHERE NOT EXISTS 的原理。🕶

让我们按照这个思路来写SQL查询语句。
首先,先找不符合题目要求的学生——那么我们就要清楚什么是题目要求📚

题目用到的表——选课、课程、学生📋


明确了题目要求,找到了源头,我们开始加判定条件🔍

从内部查询开始📚

关键词🧠
选修全部,即选修表里有全部课程(来自课程表📑)

对应逻辑语句👇

SELECT * FROM 选修; #检索选课表里所有信息 

选修全部课程的学生,即选课表里的课程对应到一名学生身上(来自学生表📝)
对应逻辑语句👇

SELECT * FROM 选修 #检索选课表里所有信息 
WHERE 选课.学号 = 学生.学号; #选修表里的课程肯定取自课程表,所以我们不用多加判断

综上,我们检索了所有选课学生的信息
但是这样我们只能知道全部的,也就是笼统的

因此,我们要找出一个特殊群体

但是这个特殊群的要求过多,我们可以先找条件少的群体最后“取反” 得出这个群体
我们先找反例——没有选修全部课程,哪怕一门,的学生

WHERE NOT EXISTS(
	SLECT * FROM 选课
	WHERE 选课.学号=学生.学号;
	); # 这样我们,就找到了没有选修全部课程的学生

再然后我们的这个条件要附加到一个检索上——因为我们是在检索课程是否选修
所以

SELECT 课程.课程号 FROM 	
	WHERE NOT EXISTS(
		SLECT * FROM 选课
		WHERE 选课.学号=学生.学号;
		); # 这样我们,就找到了没有选修全部课程的学生

综上,这就是我们的内部查询——检查每个学生是否选修了所有这些课程,

🧠然后在外部查询中筛选掉这样的学生(取反):

关键词
检索学生——

SELECT 学生.姓名 FROM 学生;

筛选学生 ——检索学生的同时加上判定条件

SELECT 学生.姓名
FROM 学生
WHERE NOT EXISTS (
    SELECT 课程.课程号
    FROM 课程
    WHERE NOT EXISTS (
        SELECT *
        FROM 选课
        WHERE 选课.学号 = 学生.学号
        # AND 选课.课程号 = 课程.课程号
        # 这句可以不要,选修课表里的课程肯定在课程表里
    )
);

综上,整段代码的逻辑是:

外部查询检查每个学生是否选修了所有课程。
内部查询检查每个课程是否被当前学生选修。
如果存在一个课程没有被当前学生选修,内部查询返回结果集不为空。
外部查询根据内部查询的结果,如果结果集为空(即不存在任何一个课程没有被选修),则选择该学生。


总结

提示:这里对文章进行总结:

嵌套查询的重在通过练习来理解其内在逻辑

在这之前一定要明确,内部查询外部查询的概念,

下一篇,我 结合实际要求帮助大家巩固之前所讲的概念以及重难点🏫