【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;
相关推荐
教练、我想打篮球4 分钟前
117 javaweb servlet+jsp 项目中修改了 数据库连接配置, 却怎么都不生效
java·servlet·jdbc·jsp
你不是我我6 分钟前
【Java 开发日记】我们来说一说 Redis IO 多路复用模型
java·开发语言·redis
SadSunset9 分钟前
(13)复杂查询
java·笔记·架构·mybatis
浩瀚地学9 分钟前
【Java】ArrayList
java·开发语言·经验分享·笔记
阿杰同学17 分钟前
Java 设计模式 面试题及答案整理,最新面试题
java·开发语言·设计模式
这样の我18 分钟前
java 模拟chrome指纹 处理tls extension顺序
java·开发语言·chrome
Genevieve_xiao22 分钟前
【数据结构与算法】【xjtuse】面向考纲学习(下)
java·数据结构·学习·算法
4311媒体网24 分钟前
php和c++哪个更好学?C++难学吗?
java·c++·php
毕设源码-朱学姐30 分钟前
【开题答辩全过程】以 基于SpringBoot的流行音乐网站的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
jiayong2332 分钟前
Spring 框架完全指南
java·后端·spring