news 2026/5/7 8:28:10

8、查询没有学全所有课的同学的学号、姓名(高性能写法——

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
8、查询没有学全所有课的同学的学号、姓名(高性能写法——

几种更高效、更健壮的写法,并对比它们的性能差异和适用场景👇


一、原 SQL 的问题分析

select Student.s_no, Student.sname from Student, Sc where Student.s_no=Sc.s_no group by Student.s_no, Student.sname having count(c_no) < (select count(*) from Course);

存在两个潜在问题:

  1. 内连接会丢失未选课的学生:完全没选课的同学,不会出现在结果里。
  2. 性能一般:全表聚合 + 子查询,在数据量大时开销较高。

二、高性能写法推荐(按性能从高到低排序)

✅ 写法 1:NOT EXISTS(性能最优,推荐)

利用NOT EXISTS的半连接特性,避免全表聚合,能高效利用索引:

sql

SELECT s.s_no, s.sname FROM Student s WHERE NOT EXISTS ( -- 核心:不存在“学生未选的课程” SELECT 1 FROM Course c WHERE NOT EXISTS ( SELECT 1 FROM Sc sc WHERE sc.s_no = s.s_no AND sc.c_no = c.c_no ) );

优势

  • 无需GROUP BY和聚合函数,减少排序开销。
  • 能利用Sc(s_no, c_no)的联合索引,快速判断学生是否选了某门课。
  • 包含完全没选课的学生。

✅ 写法 2:LEFT JOIN + COUNT(兼容 NULL,性能次优)

用左连接保留所有学生,统计有效课程数:

sql

SELECT s.s_no, s.sname FROM Student s LEFT JOIN Sc sc ON s.s_no = sc.s_no GROUP BY s.s_no, s.sname HAVING COUNT(DISTINCT sc.c_no) < (SELECT COUNT(*) FROM Course);

优化点对比原 SQL

  • LEFT JOIN替代内连接,保留了未选课学生。
  • COUNT(DISTINCT sc.c_no)避免重复选课导致的计数错误。
  • 可利用Sc(s_no, c_no)索引加速分组。

✅ 写法 3:相关子查询 (易读,适合小数据量)

直接在WHERE中计算每个学生的选课数:

sql

SELECT s.s_no, s.sname FROM Student s WHERE ( SELECT COUNT(DISTINCT sc.c_no) FROM Sc sc WHERE sc.s_no = s.s_no ) < (SELECT COUNT(*) FROM Course);

特点

  • 逻辑直观,易理解。
  • 数据量小时性能尚可,大数据量下不如NOT EXISTS高效。

三、关键性能优化技巧

  1. 必建索引

    • Sc(s_no, c_no):覆盖索引,用于快速统计学生选课数和判断课程是否已选。
    • Course(c_no):主键索引,加速总课程数统计。
  2. 避免陷阱

    • 不要用NOT IN:当Sc.s_no存在 NULL 值时,NOT IN会返回空结果,且无法利用索引。
    • 不要省略DISTINCT:若Sc表存在重复选课记录,会导致COUNT(c_no)计数偏大。

四、性能对比表

表格

写法性能可读性适用场景
NOT EXISTS⭐⭐⭐⭐⭐中等大数据量、生产环境
LEFT JOIN + COUNT⭐⭐⭐⭐中等数据量、兼容 NULL
相关子查询⭐⭐⭐小数据量、教学场景
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/7 8:20:03

Arduino项目避坑:L298N驱动12V电磁铁时,如何解决电流过大与发热问题?

Arduino项目实战&#xff1a;L298N驱动12V电磁铁的电流控制与散热优化 电磁铁在机器人、自动化控制等领域应用广泛&#xff0c;但很多创客在使用L298N模块驱动12V电磁铁时&#xff0c;常常遇到模块发烫、动力不足甚至烧毁Arduino主板的问题。上周我在工作室测试一个自动锁装置时…

作者头像 李华
网站建设 2026/5/7 8:18:37

ROS2 Humble Docker镜像瘦身与优化实战:从2GB到1GB的完整清理指南

ROS2 Humble Docker镜像瘦身与优化实战&#xff1a;从2GB到1GB的完整清理指南 在容器化开发中&#xff0c;镜像体积直接影响着CI/CD流水线的效率和资源利用率。一个未经优化的ROS2 Humble镜像很容易膨胀到2GB以上&#xff0c;这不仅拖慢构建和部署速度&#xff0c;还会增加存储…

作者头像 李华
网站建设 2026/5/7 8:15:37

Flutter动画高级技巧

Flutter动画高级技巧 1. 核心概念 1.1 动画基础 Animation&#xff1a;动画对象&#xff0c;管理动画的状态和值AnimationController&#xff1a;控制动画的播放、暂停、反转等Tween&#xff1a;定义动画的开始和结束值Curve&#xff1a;动画曲线&#xff0c;控制动画的缓动效果…

作者头像 李华
网站建设 2026/5/7 8:09:44

Cortex-M33调试架构与断点单元深度解析

1. Cortex-M33调试架构概览在嵌入式系统开发中&#xff0c;高效的调试工具是提高开发效率的关键。Arm Cortex-M33处理器作为面向物联网和嵌入式应用的主流芯片&#xff0c;其调试子系统设计体现了现代嵌入式处理器的典型特征。调试系统主要由两部分构成&#xff1a;断点单元(BP…

作者头像 李华