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

2023-05-16

SELECT SN
FROM S
WHERE NOT EXISTS(SELECT *
             FROM C
             WHERE NOT EXISTS(SELECT *
                         FROM SC
                         WHERE SNO = S.SNO AND CNO = C.CNO))

今天在看数据库的时候遇到这个问题

想了很久,脑子越想越乱。。。

连续两个NOT EXISTS,怎么就出来了选修了全部课程的学生呢?

然后翻到大神的文章,感谢!

现在懂了

---------------------------------------------------原文如下------------------------------------------------------------------

首先头脑中有三点概念:

1. EXISTS 子查询找到的提交

    NOT EXISTS 子查询中 找不到的提交

    说明:不要去翻译为存在和不存在,把脑袋搞晕。

2. 建立程序循环的概念,这是一个动态的查询过程。如 FOR循环 。

3. Exists执行的流程Exists首先执行外层查询,再执行内存查询,与IN相反。流程为首先取出外层中的第一元组,再执行内层查询,

    将外层表的第一元组代入,若内层查询为真,即有结果时。返回外层表中的第一元 组,接着取出第二元组,执行相同的算法。一直到扫描完外层整表

         for(int i =0;  i<>EOFout;i++)

                 {

                     for (int j = 0 ; j<EOFint,j++)

                 }

然后再来看一个例子: 三张表  学生表student (Sno,Sname),  课程表course (Cno,Cname) 选课表SC(Sno,Cno)

要求查询出 :选修了全部课程的学生姓名

我的思路:

首先学生的选课信息存在于SC表中, 要想知道某个学生是否选修了全部课程,至少我们需要知道一共有

几门课程,这是首要的条件。其次,学生选修了与否,我们又要扫描SC全表,统计出选修了所有课程的

学生号,最后在STUDENT表中根据学生号打出姓名 。

语句如下: (已测试)

select Sname from student             

 where Sno IN

   (select Sno from SC

   group by Sno //根据Sno分组,统计每个学生选修了几门课程。如果等于course的总数,就是我们要找的Sno

     having count(*) = (select count(*) from course ))    //统计course中共有几门课程

另一种思路:

        引入:将题目换为 查找学号为 00003 没有选修的科目  

        思路:我们可以将已知学号代入,把每一个科目代入(循环),这将形成1*count(*)种组合。

将这组成作为条件,一一与SC表种进行比对,找不到匹配的我们提交 。

                 select Cname from course  where

                          not exists               //找不到的组合,提交course

                               (select * from SC where course.cno = SC.cno and sno = ''00003'')

//在SC中匹配

换个题目: 查找没有 没有选修科目的学生姓名

      思路:学号未知 , 科目未知,说明有两个未知变量。应该有两个EXISTS。我们可以扫描

student 和 course共有 s * c 中组合,将这些组合与SC的每一项进行匹配,注意s*c组合已经包含所

有可能。如果全部找到 ,就说明已经选修了全部课程。找不到就说明有课程没选修 。再将没选修的的提交给上一exists 循环 。若上一exists 不存在的再提交给外循环。

                        select Sname from student

                           where NOT exists        //

                              (select  * from course

                               where NOT exists      //不存在的提交给course

                                (select * from SC where

                                    Sno = student.sno  and cno = Course.Cno))   // 代入两个未知变量

回头看,就是我们第一个引出的题目: 选修了全部课程的学生姓名

最后详细回答你的问题:数据库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);

理解如下:    查询选修了全部课程的学生姓名。   
不用管怎么样,第一个select 必定是在 student 表里选 sname 既:
     SELECT Sname
         FROM Student
加上条件即: where
条件是什么呢? 条件就是: 查询选修了全部课程的
因为没有(任意一个)谓词,只能用 EXISTS 或者 NOT EXISTS 来表示。这点理解吧?
所以要把条件翻译成 : 不存在一门课程这个学生没有选修.
where后面就是  不存在(NOT EXISTS) (
        一门课程这个学生没有选修
)

接下来就是把Course表中的课程依次拿出来找出没有选修的 
怎么找呢?  因为 NOT EXISTS 子查询中找不到的提交
另外你要明白 NOT EXISTS 查询都是相关查询
所以只要把 在最后一个select 中  
                         WHERE Sno= Student.Sno AND Cno= Course.Cno);
就是将这个同学通过 SC 表 和  Crouse的 课程连接一遍,找到连接不上的,即: 没有选修的, 这样就找到了一门课这个学生没有选修, 存在没有选修的课,那么该学生被pass掉了,一次进行一个同学的判断  。

若你学过程序编程,可以看下面的内容, 若没有则可忽略。
上述是理解是数据库系统内部的实现,可以用for循环表示
 for(i=1; i<student.length( 学生的总人数); i++){
          for(i=j;j<Crouse.length(总的课门数); j++){
                 条件就是:
                  没有一门课没有选修                                                         
            }
   }

最后你找记住 
1. 第一个select 就是 你要选的就是  学生
    SELECT Sname
         FROM Student
2. 第二个 select 就是  课程
3. 第三个select 就是  学生和课程发生关系的表  SC选修表
   让他们连接起来



固定的模式 1 你要的结果的表  学生
           2  满足条件的表   课程表
           3  产生关系的表   选修表
             where    通过选修表把他们连接起来

============================

查询select----存在量词查询

exists代表存在量词ョ,该查询结果没有值,只有逻辑值真true和逻辑假false两个值。

ex41:查询所有选修了001课程的学生名单

select sname
from student a
where exists ( 
select *
from sc b
where a.sno=b.sno and cno='001')

ex42:查询没有选修了001课程的学生名单

select sname
from student a
where not exists ( 
select *
from sc b
where a.sno=b.sno and cno='001')

ex43:查询选修了所有课程的学生名单。

由于SQL中没有全称量词,可以这样理解:查询这样的学生,没有一门课程他没有选

select sname
from student a
where not exists ( 
select *
from course b
where not exists (
select *
from sc c
where a.sno=c.sno and c.cno=b.cno))

注意:SQL没有蕴涵谓词,可以使用等价变换进行转换

p→q ≡ ┑p∨q

ex43:查询至少选修了学生95002选修的全部课程的学生名单。

将查询进行变换:

p表示的谓词:95002选修了课程y

q表示的谓词:学生x选修了课程y

该查询转换为:( y)p→q

进一步转换:( y)p→q ≡

┑(ョy( ┑(p→q))) ≡ ┑(ョy( ┑(┑p∨q)))

≡ ┑ョy(p∧q) 德模根定律

它所表达的含义为:不存在这样的课程y,95002选修了y而x没有选,SQL语句如下:

select sname,sno
from student a
where sno <> '95002' and not exists ( 
select *
from sc b
where sno='95002' and not exists (
select *
from sc c
where a.sno=c.sno and c.cno=b.cno))

Student:学生表

Course:课程表

SC:学生选课表 

SELECT 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
 
          )
 
    );
可以看到SQL语句中用了两次EXISTS子查询,造成了理解的困难。

使用 EXISTS 关键字引入一个子查询时,就相当于进行一次存在测试。外部查询的 WHERE 子句测试子查询返回的行是否存在。子查询实际上不产生任何数据;它只返回 TRUE 或 FALSE 值。

所以,我们可以将子查询转为如下的代码去理解:

SELECT XXX FROM TABLE WHERE EXISTS YYY; =>
 
if (YYY) 
  return SELECT(XXX);
NOT EXISTS 反过来理解就好了。

所以,查询选修了全部课程的学生姓名的SQL语句理解,我们可以从最里层往外去剖析:

查询选课表中与学生表中的学号和课程表中的课程号相等的数据,通俗的含义是:查询学生表中每个学生对于课程表中的课程的选课数据,这样查询的意义在于,万一选课表中有的学生不在学生表中或者有的课程不在课程表中呢?所以现在我们真正得到了每个学生的选课数据。
SELECT * FROM SC
    WHERE SC.Sno = Student.Sno AND SC.Cno = Course.Cno
扩大代码往外看,灵活地把两层 NOT EXISTS 子查询理解为找不到或不存在。
SELECT Sname FROM Student

SELECT 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
 
          )
 
    );


逐层翻译成人话就是:

1:从学生表查出学生姓名

4、5:找不到课程

8、9:不在学生选课表中

连起来就是,查出那些,不存在课程不在学生选课表中的学生的名字。
————————————————
版权声明:本文为CSDN博主「J.Feng」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/JF_2020/article/details/127826293

EXISTS:查询有结果则返回真值,查询为空则返回false。
NOT EXISTS:查询有结果返回false,查询为空返回true。
Exists执行的流程Exists首先执行外层查询,再执行内存查询,与IN相反。

假设:
课程总共有 语文,数学,英语三门课程。
现在有学生:张三:选修了语文,数学,没有选择英语。
           李四:三门课全都选修了。
 开始查询:
 一、首先从Student表中选出 张三 所在元组(也就是张三所在行),接着依次从Course表取出三门课程,
 1、首先取出语文课满足"Sno=Student.Sno AND Cno=Course.Cno"条件,即查询到了结果,则第2个NOT EXISTS返回结果false,第1个WHERE收到false,不执行任何操作。
 2、接着判断数学,同样满足,第一个WHERE不执行任何操作。
 3、最后拿出英语,"SELECT * FROM SC WHERE Sno=Student.Sno AND Cno=Course.Cno"语句查询不到结果,则第2个NOT EXISTS返回ture,第1个WHERE收到true,
 则将结果(也就是英语课程)放入结果表,也就是"SELECT * FROM Course"结果不为空, 第一个NOT EXISTS返回false,那么张三就不会被放进第一个查询的结果表,即张三没有被选中。
二、从Student表中选出 李四 所在元组,接着依次从Course表取出三门课程,
 因为李四三门课全都选修了,取出的三门课都满足"Sno=Student.Sno AND Cno=Course.Cno"条件,即查询到了结果,则第2个NOT EXISTS都返回结果false,第1个WHERE收到false,都不执行任何操作。
 最后循环结束时,"SELECT * FROM Course"没有任何结果,即没有一门课被加入第二个查询结果表中,结果为空,则第一个NOT EXISTS返回true,所以李四被放进第一个查询的结果表。得到选修全部课程的学生-李四。

主要思想:将“选修了所有课程的学生”转化为“没有一门课程不选修的学生”。查询到该学生存在没有选修的课程,
则该学生不会被放入结果集中。
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

查询选修了全部课程的学生姓名 的相关文章

  • 音视频篇 - Android 音视频涉及到的技术

    前言 现在市面上的图像 xff0c 音视频软件越来越多 xff0c 最近两年也是直播 xff0c 短视频的红利期 而图像 音视频一直是互联网视觉的入口 xff0c 掌握并熟练运用音视频 图像技术已经是当前互联网时代不可或缺的技能 xff0c
  • sockaddr_in的一个小理解

    之前一直认为是sockaddr 设计时有缺陷 xff0c 在编写网络通信时 xff0c 都使用sockaddr in xff0c 因为它将sockaddr 中的 char sa data 14 拆分为了 unsigned short sin
  • Linux虚拟机下WWW(HTTP)服务器的搭建与使用(详细)

    1 简介 1 1 关于www服务器 WWW服务器是被动程序 xff0c 只有接收到互联网中其他计算机发出的请求后才会响应 xff0c 然后WWW服务器才会使用HTTP或者HTTPS将指导文件传输到客户机的浏览器上 1 2 关于HTTP协议
  • 非抢占式优先级调度算法

    Priority scheduling is a type of scheduling algorithm used by the operating system to schedule the processes for executi
  • Eclipse中使用jstl标签库

    在MyEclipse中使用jstl标签只需导读jstl jar就能使用 xff0c 但是在Eclipse中还需要一点小套路 步骤 xff1a 一 导入jstl jar 二 导入导入standard jar 三 web xml加上如下配置 l
  • hibernate HQL 投影查询 + 多表关联

    64 Test public void testQueryProjection Session session 61 HibernateUtils openSession session beginTransaction 操作 hql 默认
  • NetEQ 算法

    NetEQ 算法中集成了自适应抖动控制算法以及语音包丢失隐藏算法 这项技术使其能够快速且高解析度地适应不断变化的网络环境 xff0c 确保音质优美且缓冲延迟最小 研究的重点是 NetEQ 模块 xff0c 其中所涉及的处理过程包括抖动消除
  • 数组的形参与实参,通过引用传递数组

    数组形参 xff1a void printValues int void printValues int void printValues int 10 以上三种是等价的 通常 xff0c 将数组形参直接定义为指针要比使用语法定义更好 第三
  • java 简单员工管理系统

    package cn test import java io import java util class Emp 64 Override public String toString return 34 Emp empNo 61 34 4
  • 关闭虚拟机vmware自动挂起

    1 xff0c 桌面右键 属性 xff0c 里的屏幕保护程序 xff0c 选 无 2 xff0c 控制面板的电源选项 xff0c 方案为 一直开着 xff0c 具体选项选 从不关机 3 xff0c 在Windows 2003 Server点
  • GTK+2.0之初始学习篇(二)—— g_signal_connect宏解释及HelloWorld

    GTK 43 2 0中利用信号 回调函数机制来处理窗口外部传来的事件 消息或信号 以下实现的是单击窗口关闭按钮 xff0c 窗口自动关闭 在程序中调用了gtk main quit 函数实现退出主循环 include lt gtk gtk h
  • linux-----页、页表、页框(块)

    基本介绍 我们知道 xff0c 在linux操作系统中 xff0c CPU在执行一个进程的时候 xff0c 都会访问内存 但CPU并不是直接访问物理内存地址 xff0c 而是通过虚拟地址空间来间接的访问物理内存地址 所谓的虚拟地址空间 xf
  • CMake交叉编译配置

    罗列一下cmake常用的命令 CMake支持大写 小写 混合大小写的命令 1 添加头文件目录INCLUDE DIRECTORIES 语法 xff1a include directories AFTER BEFORE SYSTEM dir1
  • 8086CPU的14个寄存器全称

    通用寄存器 xff1a ax accumulate register 累加器 bx based register 基地址寄存器 cx count register 计数器 dx data registered 数据寄存器 段寄存器 xff1
  • 项目开发-后台管理框架

    开发中几乎的平台都需要一个后台管理 xff0c 但是从零开发一套后台控制面板并不容易 xff0c 幸运的是有很多开源免费的后台控制面板可以给开发者使用 xff0c 那么有哪些优秀的开源免费的控制面板呢 xff1f 我在 Github 上收集
  • 项目经理必备工具-个人推荐

    点击链接 项目经理必备工具 进入详细说明
  • 如何绕过CDN找源站ip?

    如何绕过CDN找源站ip xff1f 这是一个总结帖 xff0c 查了一下关于这个问题的国内外大大小小的网站 xff0c 对其中说的一些方法总结归纳形成 xff0c 里面具体发现ip的方法不是原创 xff0c 所有参考的原贴都也贴在了后面
  • Navicat修改MySQL数据库密码就是这么简单

    方法1 xff1a 用SET PASSWORD命令 首先登录MySQL 格式 xff1a mysql gt set password for 用户名 64 localhost 61 password 39 新密码 39 例子 xff1a m
  • Axure 元件库-原型

    元件名称 xff1a 1 Axure交互原型设计指南 rp 2 PC和移动原型常用元件 rp 3 后台模板 rp 4 全局说明 rp https pan baidu com s 1vmac 08MZAKj6qsdjwIZlg 提取码 xff

随机推荐

  • Node.js 通过http调用外部接口

    通过http request发送带参数的post请求 data xff1a 发送的内容 opt xff1a 描述将要发出的请求 data xff1a 事件在数据到达时被触发 end xff1a 请求结束时触发 error xff1a 发生错
  • 想成为出色的 CTO,你要具备这七大能力

    编者按 xff1a 首席技术官这一职位在20世纪80年代出现于美国 起于做很多技术研发的大公司 xff0c 如General Electric 主要职能是将科研成果转化实际效益 简单地说 xff0c 就是一个企业中技术的最高负责人 要扮演好
  • Keil中添加自己的头文件

    xfeff xfeff 方法一 在keil的开发环境下添加 xff1a 请注意上面的系统生成的头文件目录是 xff1a xff0c 即 dd jj pp kk xff0c 其中 是相对于项目文件 uvproj 而言的 其中 表示项目文件所在
  • http authorization 基本认证

    最近做的一个项目需要与其它系统对接接口 xff0c 对方提供的是webservice的接口 xff0c 并且需要Basic Authorization基本认证 xff0c 一开始都是用postman请求 xff0c 用户名和密码需要填在Ba
  • 终端命令安装 chrome for linux

    终端里安装chrome for linux 备注 xff1a 我是在Linux Mint 17 1 64位系统下安装的chrome for linux xff0c 其它Debian衍生版应该也是一样的 1 在终端里输入下载命令 xff1a
  • Arduino串口函数详解

    本文总结了Arduino常用串口操作函数 xff0c 函数说明部分来源于Arduino 官网串口使用指南 xff0c 示例与实验部分为自编 本文是对Arduino串口操作函数的较全面总结 xff0c 可作为工具贴查找使用 1 串口设置 xf
  • STM32CubeMX——霍尔编码器、L298N驱动电机

    前言 人生如逆旅 xff0c 我亦是行人 苏轼 临江仙 送钱穆父 目录 xff1a L298N电机驱动介绍编码器介绍电机介绍新建工程编写代码实验结果 一 L298N电机驱动介绍 B站 视频讲解 xff1a l298n电机驱动模块 电机正反转
  • AT命令拨电话,如何判断手机的状态?

    我使用AT命令拨电话 xff0c 如 xff1a ATD10086 我怎么知道我拨打的电话是否成功了呢 xff1f 比如SIM卡欠费了 xff0c 那么肯定算是没有拨通 xff1b 再比如网络有问题 xff0c 被叫方没有收到来电 xff0
  • GPS模块(GPS-NEO-6M)

    ATK NEO 6M GPS 模块简介 ATK NEO 6M V23 模块 xff0c 是 ALIENTEK 生产的一款高性能 GPS 模块 xff0c 模块核心采用 UBLOX公司的 NEO 6M 模组 xff0c 具有 50 个 通道
  • toCharArray()

    toCharArray 是将一个字符串内容转换为字符数组 xff0c 例如 String str 61 34 abc 34 System out println str toCharArray 43 34 34 将输出a b c 转载于 h
  • 基于Arduino的GPS数据解析程序

    这篇博客讲了我利用arduino来解析和转发原始nema 0813数据的思想和实现方法 因为arduino比较简单 xff0c 无法实现串口数据接收中断 xff0c 所以都写在主循环里面了 不知道代码存在何种缺陷和漏洞 xff0c 欢迎大家
  • VsCode安装和配置c/c++环境(超完整,小白专用)

    文章目录 1 vsCode配置C C 43 43 环境 1 vsCode下载和安装 1 下载Microsoft vsCode2 安装vsCode3 下载中文插件2 MinGW编译器下载和配置 1 下载MinGW2 下载后放到自己方便的目录
  • 各版本esp32和esp8266开发板引脚图(附各开发板特殊通信接口如IIC、SPI接口等默认引脚查看方法)

    目录 esp32 GPIO可用资源 1 esp32开发板 2 esp32开发板 查看特殊通信接口的方法 esp8266 esp32 GPIO可用资源 GPIO 6 11 连接到SPI Flash GPIO 34 39 只能作为输入且没有内部
  • GPS数据解析、可视化及经纬度距离计算

    一 GPS数据解析 根据NMEA协议 xff0c 我们从传感器上接收到的GPS经纬度数据格式如下 xff1a 例 xff1a GPRMC 024813 640 A 3158 4608 N 11848 3737 E 10 05 324 27
  • C语言知识点小结 | 指针 数组 结构体 堆栈 内存分配

    不掌握指针就是没有掌握C的精华 地址指向该变量单元 xff0c 地址即指针 在C C 43 43 语言中定义一个指针 xff0c 就是在栈区开辟一个内存空间用来存放它指向的内存地址 xff0c 然后给指针赋值 xff0c 就是把地址值赋值给
  • 西门子PLC S7-200SMART Modbus TCP通讯的步骤和要点

    Modbus TCP是一个非常传统 xff0c 应用广泛的通讯协议 xff0c 很多智能设备都支持该协议 西门子S7 200SMART及1200 1500系列都免费支持 xff08 300和400还是要高昂收费 xff09 xff0c 并且
  • GPRM/GNRMC定位信息的读取与解析

    GPRM GNRMC定位信息的读取与解析 参考网址 xff1a http www cnblogs com 88223100 p GPRM GNRMC Transform html 帧头 UTC时间 状态 纬度 北纬 南纬 经度 东经 西经
  • 基于Arduino 开发 MAX30102 LM35 SSD1306 观察血氧、心率和温度血氧仪

    本项目第一版本实现在arduino框架下通过MAX30102 对血氧和心率 进行实时监控 xff0c 通过LM35 对温度进行监控 所有数值在 ssd 1306 上进行显示 在血氧低过一定数值的时 xff0c 设备会通过蜂鸣器发出警报 第二
  • Python中max函数key的用法详解

    一 背景 起源于一个问题 xff1a 怎样找到字符串中出现次数最多的字符 其实使用max函数就能很轻松的解决这个问题 xff1a 代码 xff1a str1 61 34 AAAaaa8888899sssss 34
  • 查询选修了全部课程的学生姓名

    SELECT SN FROM S WHERE NOT EXISTS SELECT FROM C WHERE NOT EXISTS SELECT FROM SC WHERE SNO 61 S SNO AND CNO 61 C CNO 今天在看