山东大学 2020级数据库系统 实验一
山东大学 2020级数据库系统 实验二
山东大学 2020级数据库系统 实验三
山东大学 2020级数据库系统 实验四
山东大学 2020级数据库系统 实验五
山东大学 2020级数据库系统 实验六
山东大学 2020级数据库系统 实验七
山东大学 2020级数据库系统 实验八、九
做数据库实验一定要静得下心来,才能发现其中的错误然后进行改正。同时,如果发现 SQL 语句总是报错,“一定是你错了,只是不知道错在哪里”
其次,SQL 语句中较为复杂的点博主都进行了注释,希望大家一定要看懂思路后自己写一遍,而不是盲目的 Ctrl+C,Ctrl+V,切记切记!!
注意:实验二使用的表是:pub.student_course, pub.student, pub.course 哦,别搞错了!!
检索查询部分应该算是数据库中较为困难的一部分了,每道题我会先写出思路,同时在 SQL 语句中进行注释,希望能够看懂。
create view test2_01 as
select sid, name
from pub.student
where sid not in
(
select sid -- 选出有选课记录的同学的学号
from pub.student_course
)
2-2 找出至少选修了学号为“200900130417”的学生所选修的一门课的学生的学号、姓名(不包含这名同学)。
思路 1:
思路 2:
---------------思路 1---------------------
create view test2_02 as
select sid, name
from pub.student
where sid in
(
select sid
from pub.student_course
where sid <> '200900130417' -- 不包含这名同学
and cid = some -- 课程号至少有一个与 A 中元素相同的才满足条件
(
select cid
from pub.student_course
where sid = '200900130417'
)
)
---------------思路 2---------------------
create view test2_02 as
(
select sid, name -- 选出对应的学生的学号及姓名(此时包括学号为‘200900130417’的这名同学)
from pub.student
where sid in
(
select sid -- 选出至少有一个 cid 在 A 中的同学的 sid
from pub.student_course
where cid in
(
select cid -- 集合 A
from pub.student_course
where sid = '200900130417'
)
)
)
except--(Oracle 中是 minus 哦~~) -- 除去这名同学的信息
(
select sid, name
from pub.student
where sid = '200900130417'
)
2-3 找出至少选修了一门其先行课程号为“300002”号课程的学生的学号、姓名
思路:
第 2 步以及第 3 步可以使用 natural join 进行连接。
create view test2_03 as
select sid, name
from pub.student natural join pub.student_course
where cid in
(
select cid
from pub.course
where fcid = '300002'
)
2-4 找出选修了“操作系统”并且也选修了“数据结构”,但是没有选修“程序设计语言”的学生的学号、 姓名
思路:
(注意 Oracle 中将 except 换为 minus 就行)
create view test2_04 as
select sid, name
from pub.student
where sid in
(
(
select sid
from pub.student_course
where cid in
(
select cid
from pub.course
where name = '操作系统'
)
)
intersect
(
select sid
from pub.student_course
where cid in
(
select cid
from pub.course
where name = '数据结构'
)
)
except(Oracle 中是 minus 哦~~)
(
select sid
from pub.student_course
where cid in
(
select cid
from pub,course
where name = '程序设计语言'
)
)
)
2-5 查询 20 岁的所有有选课的学生的学号、姓名、平均成绩(avg_score,此为列名,下同)(平均成绩四舍 五入到个位)、总成绩(sum_score)
思路:
注意:函数 round(number, precision) 可以将 number 按照 precision 精确到对应位。round(avg(number), 0) 即代表将 score 的平均值保留到整数位。
create view test2_05 as
select sid, name, round(avg(score), 0) avg_score, sum(score) sum_score
from pub.student natural join pub.student_course
where age = 20
group by sid, name
2-6 查询所有课的最高成绩、最高成绩人数,test2_06 有四个列:课程号 cid、课程名称 name、最高成绩 max_score、最高成绩人数 max_score_count(一个学生同一门课成绩都是第一,只计一次,需要考虑刷 成绩情况,一个同学选了一个课程多次,两次都是最高分。如果结果错一行,可能就是没有考虑这种情 况,这里是为了考核“去重复计数”知识点的)。如果没有学生选课,则最高成绩为空值,最高成绩人 数为零
此题应该算是实验二中最难的一道了。希望我能将思路说清楚
主要用到的表如下:
思路:
1. t1, t2 表的求解过程不用多说,简单的分组查询(查询时一定要加上 cid ,因为后面要将它们连接起来);
2. 由于需要数最高分的人数,因此首先要在查询 max_score_count 部分的 from 子句中计算出 max_score (t4 表);
3. 然后针对 score 对学生进行筛选,让 t3.cid = t4.cid 以及 t3.score = t4.max_score,得出每门课的最高分的学生的信息;
4. 再进行分组后 count 得到 max_score_count;
5. 最后将这些表的信息连起来 t1.cid = t2.cid and t2.cid = t5.cid;
create view test2_06 as
select t1.cid, name, max_score, max_score_count
from
(
select cid, name
from pub.course
group by cid, name
) t1,
(
select cid, max(score) max_score
from pub.student_course
group by cid
) t2,
(
select t3.cid, count(distinct sid) max_score_count
from pub.student_course t3,
(
select cid, max(score) max_score
from pub.student_course
group by cid
) t4
where t3.cid = t4.cid
and t3.score = t4.max_score
group by t3.cid
) t5
where t1.cid = t2.cid
and t2.cid = t5.cid
2-7 查询所有不姓张、不姓李、也不姓王的学生的学号 sid、姓名 name
思路 1:
思路 2:
------------------思路 1-------------------
create view test2_07 as
select sid, name
from pub.student
where substr(name, 0, 1) <> '张'
and substr(name, 0, 1) <> '李'
and substr(name, 0, 1) <> '王'
------------------思路 2-------------------
create view test2_07 as
select sid, name
from pub.student
where name not like '张%'
and name not like '李%'
and name not like '王%'
create view test2_08 as
select substr(name, 0, 1) second_name, count(*) p_count
from pub.student
group by substr(name, 0, 1)
create view test2_09 as
select sid, name, score
from pub.student natural join pub.student_course
where cid = '300003'
2-10 找出同一个同学同一门课程有两次或以上不及格的所有学生的学号、姓名(即一门课程需要补考两次 或以上的学生的学号、姓名)
思路 1:
思路 2:
----------------思路 1-----------------
--思路 1有点缺陷,建议思路 2--
create view test2_10 as
select sid, name
from pub.student
where sid in
(
select sid
from pub.student_course S
where score < 60
and exists
(
select sid
from pub.student_course T
where S.cid = T.cid
and T.score < 60
and S.score <> T.score
)
)
----------------思路 2-----------------
create view test2_10 as
select sid, name
from pub.student
where sid in
(
select sid
from
(
select sid, cid, count(*) s_count
from pub.student_course
where score < 60
group by sid, cid
)
where s_count >= 2
)
再次强调:一定是看懂思路之后自己实践哈~~
有问题还请斧正!