【SQL实验】高级查询(二)

完整代码在文章末尾【文中可能会有不准确或待完善之处,恳请各位读者不吝批评指正,共同促进学习交流


**二、**下载educ20201027.bak,打开SSMS(集成管理器),**使用菜单操作:**将素材的中的educ20201027.bak数据还原到数据库【本文跳过这个内容】

【如果做过之前的实验的话(专栏中有),就没有必要去还原了,直接用前面建的EDUC,数据是一样的】如果没有数据库,需要去还原一下

问题:

1.查询成绩大于90分的学生的学号和姓名。(使用连接和子查询两种方法)

连接查询:

复制代码
SELECT student.sno, student.sname
FROM student
JOIN sc ON student.sno = sc.sno
WHERE sc.grade > 90;

子查询:

复制代码
SELECT sno, sname
FROM student
WHERE sno IN (
    SELECT sno
    FROM sc
    WHERE grade > 90
);

SQL 子查询是嵌套在其他查询中的查询。通常子查询用于在主查询中对表数据进行进一步的条件筛选

  • 连接查询 :直接连接 studentsc 表,过滤出符合条件的数据。结果包含 student 表中所有符合条件的记录。
  • 子查询 :先在 sc 表中查找符合条件的学号,再在 student 表中基于学号进行筛选,达到相同的结果。

运行结果不同的原因

  1. 连接查询的结果可能包含重复记录

    如果在 sc 表中,一个学生有多条成绩记录,且每条记录都满足 grade > 90 的条件,连接查询会返回多条结果。例如,Y71814001(陈靖)有多条成绩都大于 90,就会出现重复

  2. 子查询的结果通常是去重的

    子查询会首先筛选出符合条件的学号,且在主查询中只查找这些学号。即使 sc 表中有多个相同的学号,只要它们在子查询中存在,主查询结果中也只会出现一次

如果希望在连接查询中去重,可以使用 DISTINCT

复制代码
SELECT DISTINCT student.sno, student.sname
FROM student
JOIN sc ON student.sno = sc.sno
WHERE sc.grade > 90;

2.查询所有学生的学号、姓名,所选课程的课程号、课程名和成绩信息

复制代码
SELECT student.sno, student.sname, course.cno, course.cname, sc.grade
FROM student
JOIN sc ON student.sno = sc.sno
JOIN course ON sc.cno = course.cno;

3.查询每一门课的间接先修课(先修课的先修课),显示信息包括课程号、间接先修课课程号。

复制代码
SELECT c1.cno AS 课程号, c3.cno AS 间接先修课课程号
FROM course c1
JOIN course c2 ON c1.cpno = c2.cno
JOIN course c3 ON c2.cpno = c3.cno;

通过多次连接同一张课程表,寻找课程的间接先修课程

FROM course c1:从课程表 course 中选取数据,并将其赋予别名 c1

4.查询"Y71814001"号同学选修,但"Y71814003"号同学未选的课程的课程号及课程名

复制代码
SELECT course.cno, course.cname
FROM course
JOIN sc AS sc1 ON course.cno = sc1.cno
LEFT JOIN sc AS sc2 ON course.cno = sc2.cno AND sc2.sno = 'Y71814003'
WHERE sc1.sno = 'Y71814001' AND sc2.sno IS NULL;

sc1 表示学生 'Y71814001' 选修的课程

LEFT JOIN 没有匹配的记录时会返回 NULL,可以确保只选择 'Y71814001' 选了但 'Y71814003' 没选的课程。

5.查询程熙的成绩

复制代码
SELECT course.cno, course.cname, sc.grade
FROM student
JOIN sc ON student.sno = sc.sno
JOIN course ON sc.cno = course.cno
WHERE student.sname = '程熙';

6.查询没有参加任何一门考试的学生姓名

复制代码
SELECT sname
FROM student
WHERE sno NOT IN (
    SELECT sno
    FROM sc
);
  1. 找出选修'02'号课程并且分数大于该课程平均分的学生信息(包括学号、成绩)。

    SELECT sc.sno, sc.grade
    FROM sc
    WHERE sc.cno = '02'
    AND sc.grade > (
    SELECT AVG(grade)
    FROM sc
    WHERE cno = '02'
    );

  1. 计算选修了'02'号课程的每个学生的学号和平均成绩。

    SELECT sno, AVG(grade) AS 平均成绩
    FROM sc
    WHERE sno IN (
    SELECT sno
    FROM sc
    WHERE cno = '02'
    )
    GROUP BY sno;

错误写法:先筛选后分组,得到的是每个学生的2号课程成绩,不是平均成绩

复制代码
SELECT sno, AVG(grade) AS 平均成绩
FROM sc
WHERE cno = '02'
GROUP BY sno;

AVG :聚合函数,返回选定记录的平均值

9.查询程熙高于其所有选修课程平均分的那些课程的课程名和成绩。(例如:该同学选修了离散数学,分数为90,而他选修的所有课程平均分为85,则显示)

复制代码
SELECT course.cname, sc.grade
FROM student
JOIN sc ON student.sno = sc.sno
JOIN course ON sc.cno = course.cno
WHERE student.sname = '程熙'
AND sc.grade > (
    SELECT AVG(grade)
    FROM sc
    --WHERE sno = student.sno
);

10.查询每个学生的成绩在80分以上的各有多少门,显示姓名和门数。

复制代码
SELECT student.sname, COUNT(*) AS 成绩在80分以上门数
FROM student
JOIN sc ON student.sno = sc.sno
WHERE sc.grade > 80
GROUP BY student.sname;

在上面代码中定义别名时报错

在 SQL 中定义别名时,有一些限制和要求需要遵守,具体如下:

  1. 命名规则
  • 字符集 :别名可以使用字母、数字和下划线(_),但不能以数字开头

  • 长度限制:不同的数据库管理系统(DBMS)对别名的最大长度有不同的限制

  1. 关键字和保留字
  • 避免使用关键字 :避免将别名命名为 SQL 的关键字(如 SELECTFROMWHERE 等),以免引起语法错误或混淆。
  1. 唯一性
  • 在同一查询中必须唯一:在同一 SQL 查询中,别名必须是唯一的,以避免歧义。
  1. 使用场景
  • 仅在查询中有效:别名仅在特定的查询中有效,并不会在数据库的其他地方(如表、列)保留。别名的作用是使查询结果更加易读或便于进一步处理。
  1. 引用方式
  • 使用空格时的引用 :如果别名包含空格或特殊字符,需要用方括号、反引号或双引号将其括起来。

其他方式:

复制代码
SELECT student.sname, A.num AS "80分以上的门数"  
FROM student  
JOIN (  
    SELECT sno, COUNT(*) AS num  
    FROM sc  
    WHERE sc.grade > 80  
    GROUP BY sc.sno  
) AS A  
ON student.sno = A.sno;




SELECT student.sno, student.sname, COUNT(*)  
FROM student,sc 
where student.sno = sc.sno and grade> 80
group by student.snastudent.sname

完整代码:

复制代码
--二
-- 1. 查询成绩大于90分的学生的学号和姓名(使用连接和子查询两种方法)
-- 使用连接
--SELECT student.sno, student.sname
SELECT DISTINCT student.sno, student.sname
FROM student
JOIN sc ON student.sno = sc.sno
WHERE sc.grade > 90;

-- 使用子查询
SELECT sno, sname
FROM student
WHERE sno IN (
    SELECT sno
    FROM sc
    WHERE grade > 90
);

-- 2. 查询所有学生的学号、姓名,所选课程的课程号、课程名和成绩信息
SELECT student.sno, student.sname, course.cno, course.cname, sc.grade
FROM student
JOIN sc ON student.sno = sc.sno
JOIN course ON sc.cno = course.cno;

-- 3. 查询每一门课的间接先修课(先修课的先修课),显示信息包括课程号、间接先修课课程号
SELECT c1.cno AS 课程号, c3.cno AS 间接先修课课程号
FROM course c1
JOIN course c2 ON c1.cpno = c2.cno
JOIN course c3 ON c2.cpno = c3.cno;

-- 4. 查询"Y71814001"号同学选修,但"Y71814003"号同学未选的课程的课程号及课程名
SELECT course.cno, course.cname
FROM course
JOIN sc AS sc1 ON course.cno = sc1.cno
LEFT JOIN sc AS sc2 ON course.cno = sc2.cno AND sc2.sno = 'Y71814003'
WHERE sc1.sno = 'Y71814001' AND sc2.sno IS NULL;

-- 5. 查询程熙的成绩
SELECT course.cno, course.cname, sc.grade
FROM student
JOIN sc ON student.sno = sc.sno
JOIN course ON sc.cno = course.cno
WHERE student.sname = '程熙';

-- 6. 查询没有参加任何一门考试的学生姓名
SELECT sname
FROM student
WHERE sno NOT IN (
    SELECT sno
    FROM sc
);

-- 7. 找出选修'02'号课程并且分数大于该课程平均分的学生信息(包括学号、成绩)
SELECT sc.sno, sc.grade
FROM sc
WHERE sc.cno = '02'
AND sc.grade > (
    SELECT AVG(grade)
    FROM sc
    WHERE cno = '02'
);

-- 8. 计算选修了'02'号课程的每个学生的学号和平均成绩
SELECT sno, AVG(grade) AS 平均成绩
FROM sc
WHERE sno IN (
    SELECT sno
    FROM sc
    WHERE cno = '02'
)
GROUP BY sno;


-- 9. 查询程熙高于其所有选修课程平均分的那些课程的课程名和成绩
SELECT course.cname, sc.grade
FROM student
JOIN sc ON student.sno = sc.sno
JOIN course ON sc.cno = course.cno
WHERE student.sname = '程熙'
AND sc.grade > (
    SELECT AVG(grade)
    FROM sc
    WHERE sno = student.sno
);

-- 10. 查询每个学生的成绩在80分以上的各有多少门,显示姓名和门数
SELECT student.sname, COUNT(*) AS 成绩在80分以上门数
FROM student
JOIN sc ON student.sno = sc.sno
WHERE sc.grade > 80
GROUP BY student.sname;
相关推荐
大厂码农老A2 分钟前
面试官:“聊聊你最复杂的项目?” 为什么90%的候选人第一句就栽了?
java·面试
爱读源码的大都督9 分钟前
Java已死?别慌,看我如何用Java手写一个Qwen Code Agent,拯救Java
java·人工智能·后端
lssjzmn9 分钟前
性能飙升!Spring异步流式响应终极指南:ResponseBodyEmitter实战与架构思考
java·前端·架构
LiuYaoheng25 分钟前
【Android】View 的基础知识
android·java·笔记·学习
勇往直前plus33 分钟前
Sentinel微服务保护
java·spring boot·微服务·sentinel
星辰大海的精灵33 分钟前
SpringBoot与Quartz整合,实现订单自动取消功能
java·后端·算法
小鸡脚来咯36 分钟前
一个Java的main方法在JVM中的执行流程
java·开发语言·jvm
江团1io037 分钟前
深入解析三色标记算法
java·开发语言·jvm
天天摸鱼的java工程师1 小时前
RestTemplate 如何优化连接池?—— 八年 Java 开发的踩坑与优化指南
java·后端
你我约定有三1 小时前
java--泛型
java·开发语言·windows