前言
那么今天我们来学sql。
第七问
题目:查询学过编号为01的课程也学过编号为02课程的学生的学号、姓名。
分析:
- 课程号c_id
- 学号s_id
- 学生姓名s_name
学号和姓名在一张表中,学号和课程号在一张表中。
我们把问题拆成两个子问题:
- 编号为01的课程也学过编号为02课程的学生的学号
- 学号对应的姓名
对于第一个问题,我们把表score
分别筛选出c_id = 01
和c_id = 02
的字段然后自联得到视图v1。
然后通过视图v1查询出学生姓名有两种方法,学生表和v1连接以及学生表s_id in v1
,那么我们最后得出结果:
select s1.s_id,s1.s_name from Student s1
where s1.s_id in
(
//注意这边,连表之后的表要进行查询操作才能得到对应的视图
select s2.s_id from
(
(select s_id from score where c_id = '01') s2
join
(select s_id from score where c_id = '02') s3
on s2.s_id = s3.s_id
)
)
第八问
题目:查询课程编号为02的总成绩
分析:
- 课程编号c_id
- 总成绩SUM(score)
那么使用表score
就可以实现,注意使用having
筛选而非where
。
select SUM(s_score) from score
GROUP BY c_id
HAVING c_id = '02'
第九问
问题:查询所有课程成绩小于60分的学生的学号和姓名
分析:
其实这个问题存在歧义,到底是所有课程小于60分的所有学生还是任意一门课程小于60分的所有学生。
那我这边假设是前者。
- 学号s_id
- 姓名s_name
- 所有成绩小于60max(s_score)<60
SELECT s1.s_id,s1.s_name FROM Student s1
JOIN
(SELECT s_id FROM score GROUP BY s_id HAVING MAX(s_score)<60) s2
on s1.s_id = s2.s_id
第十问
题目:查询没有学全所有课的学生的学号和姓名
分析:又是所有课,所以我们采用和之前一样的方法,计算出总的课程数count_c
,然后找出所有score表中记录数小于count_c
的学生(要使用group by
聚类,所以又是使用having
),然后再获得其姓名。
- 学号s_id
- 姓名s_name
- 课程号c_id
- 课程数
select count(*) from course
SELECT s1.s_id,s1.s_name FROM Student s1
JOIN
(SELECT s_id FROM score GROUP BY s_id HAVING COUNT(c_id) < (SELECT COUNT(*) FROM course)) s2
ON s1.s_id = s2.s_id
第十一问
题目:查询至少有一门课与学号为“01”的学生所学课程相同的学生的学号和姓名
分析:
看到至少有一门,那么我们很容易想到取反,就是说,先找到和01学生一门课都不同的学生再取反(这里要使用and s_id != 01
来排除学生自己)。
那么如何找到一门课都不相同呢?
先查询出01学生学过的所有课程,然后使用not in
字段来获取课程号不同于这些课程的行。
- 学号s_id
- 课程号c_id
- 姓名s_name
SELECT s_id,s_name FROM Student
WHERE s_id NOT IN
(SELECT s_id FROM score WHERE c_id NOT IN(SELECT c_id FROM score WHERE s_id = '01'))
AND s_id != '01'