【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;
相关推荐
熬夜加班写代码32 分钟前
SpringBoot【九】mybatis-plus之自定义sql零基础教学!
java·spring boot·后端·sql·程序员·mybatis
TANGLONG22235 分钟前
【初阶数据结构与算法】初阶数据结构总结之顺序表、单链表、双链表、栈、队列、二叉树顺序结构堆、二叉树链式结构(附源码)
java·c语言·数据结构·c++·python·算法·面试
謬熙2 小时前
Vue.js:代码架构组成与布局设置
java·vue.js·前端框架
鸽鸽程序猿2 小时前
【算法】【优选算法】分治(下)
java·算法·分治
LeonNo114 小时前
k8s, deployment
java·容器·kubernetes
娶个名字趴4 小时前
事务的传播机制
java
学习中的问题5 小时前
同步数据至ES时,数据丢失问题处理
java·elasticsearch
☼YJLH☾5 小时前
第二章,SQL映射文件
java·sql·tomcat
八月五5 小时前
Tomcat项目本地部署
java·tomcat
MuYan~6 小时前
kafka java 小记录
java·分布式·kafka