SQL:实验四 数据库查询语言(二)
实验四 数据库查询语言(二)
一、实验目的
1.掌握Management Studio的使用。
2.掌握SQL中连接查询和嵌套查询的使用。
二、实验内容
1.找出所有任教“数据库”的教师的姓名。
select teac_name
from teacher
where teac_id in (
select teac_id
from courseTeacher
where course_id in(
select course_id
from course
where Course_name='数据库')
2.找出学号为“980101011”的学生选修的课程号和课程名。
select Course_id, Course_name
from Course
where Course_id in (select Course_id
from StudentGrade
where Stu_id='980101011')
3.“涂杰杰”所选修的全部课程号及成绩。(注意:school中有同名,即有两名学生叫“涂杰杰”。)
select student.Stu_id, Course_id,grade
from StudentGrade,student
where Student.Stu_name ='涂杰杰' and Student.Stu_id=StudentGrade.Stu_id
(因为重名所以个人考虑一下需要经过stu_id加以区分当然题目不要求这样,理解即可!)
4.检索选修课程号为“0109”或“0111”的学生学号、姓名和所在班级编号。
select stu_id,stu_name,Class_id
from Student
where Stu_id in(select Stu_id
from StudentGrade
where Course_id in('0109','0111')
)
学习一下在SQL结构化查询语言的注释语句
5.查询“0203”课程的最高分的学生的学号。
select Stu_id
from StudentGrade
where Course_id ='0203' and grade in(select max(grade)
from StudentGrade)
选修了以“01”开头的课程的学生学号,姓名,选课的课程号。
select distinct student.stu_id,stu_name,course_id
from student,studentgrade
where student.stu_id in
(select distinct stu_id
from studentgrade
where Course_id like '01%') and Course_id like '01%'
这道题的表无非就是student和studentgrade表,通过直接连接就好,没必要那么复杂使用嵌套连接。
参考老师的答案:
--6 right
select Student.Stu_id,Student.Stu_name,StudentGrade.Course_id
from Student,StudentGrade
where Course_id like '01%' and Student.Stu_id =StudentGrade.Stu_id
7.没有选修以“01”开头的课程的学生学号,姓名,选课的课程号。(用子查询完成,提示not in或not exists。需考虑没选课的学生,仔细对比上题)
--7 right
select Student.Stu_id,Student.Stu_name,StudentGrade.Course_id
from Student,StudentGrade
where Course_id not like '01%' and Student.Stu_id =StudentGrade.Stu_id
8.找出“苏贤兴”同学所学课程的名称和成绩。
--8 right
select Course_name,Grade
from Student,StudentGrade,Course
where Stu_name='苏贤兴' and Student.Stu_id=StudentGrade.Stu_id and Course.Course_id=StudentGrade.Course_id
9.统计年龄大于30岁的学生的人数。
--9
select COUNT(*) '大于30岁的人数'
from Student
where YEAR(GETDATE())-YEAR(Student.Birthday)>30
10.统计数据结构有多少人80分或以上。
--10
select COUNT(*) 'DS80分及以上人数'
from Course,StudentGrade
where Course.Course_name ='数据结构' and Course.Course_id=StudentGrade.Course_id and Grade>=80
11.统计各系开设班级的数目(系名称、班级数目),并创建结果表。(需考虑没有班级的系)
这道题目比较困难,需要用到蛮多的函数尤其是count;而且牵扯的表有点多;要创建一个全新的结果表。
这是老师给的答案;实验成功了但是我一直没有找到这个结果新表在哪里?!
屏蔽掉into语句后显示的结果还是比较好的。
老师的这段代码采用连接查询的外连接。详细参考课本P102 3.外连接
这是我的错误尝试;一开始简单地想用group搞定。
--11 error
select Depar_id,count(class_id) 'num'
from class,Deparment
group by Class_id
having Class.Depar_id=Deparment.Depar_id
最后还是使用老师的代码比较合适:
--11 right
select depar_name,count(class_id) as 班级数目
into newtable1
from deparment left outer join class on(deparment.depar_id=class.depar_id)
group by depar_name
12.统计各门课程的选修人数,并按人数降序排列,找出排名前三位的课程。(提示:可以使用TOP 3)
--12
select Top 3 course_id ,count(*) 'num'
from StudentGrade
group by course_id
order by count(*) Desc
这道题目使用的是升降序还有就是TOP的技术方法。
13.统计各门课程的选修人数,并按人数降序排列,找出排名前三位的课程。(上述使用TOP 3,却不能处理人数并列的情况。试考虑一种方法能处理人数并列的情况。)
恕我愚昧这道题目我是真的不会啊!老师给的答案里面是在having语句里面在嵌套一个select语句。我是真的没有想到还可以这么玩,真会玩!
--13 借鉴老师的代码
select course_id,count(*)
from studentgrade
group by course_id
having count(*) in(select distinct top 3 count(*)
from studentgrade
group by course_id
order by count(*) desc)
order by count(*) desc
14.统计每科目的最高分、最低分,平均分、总分,并以中文列名显示。
--14
select Course_name,MAX(grade) 'Highest',MIN(grade) 'Lowest',AVG(grade) 'Avg',SUM(grade) 'Sum'
from Course,StudentGrade
where Course.Course_id=StudentGrade.Course_id
group by studentgrade.Course_id,Course_name
15.所有科目成绩都在70分以上的学生姓名(要求:至少采用两种方法)。
方法一:这个就是直接连接
--15_1
select Stu_name
from student,StudentGrade
where Student.Stu_id=StudentGrade.Stu_id
group by Stu_name,Student.Stu_id,StudentGrade.Stu_id
having min(grade)>70
方法二:嵌套查询的方式
--15_2
select Stu_name
from Student
where Stu_id in (select Stu_id
from StudentGrade
group by Stu_id
having min(Grade)>70
)
16.“数据库”课程得最高分的学生的学号、姓名和所在系。
上图是我的实现结果。但是老师的和我的不一样?!
这个就是通过老师的实验代码得到的结果。很显然,top1 只能得到一个学生但是若是有多个同分的同学那么应该怎么处理呢?
重新修改一下代码最终和老师的代码一致——在where语句中缺少一个条件就是student表中的stu_id要和studentgrade表中的stu_id要一致。这个还不是正确的答案。同分问题还是没有解决。
解决的思路:嵌套连接。找到和数据库成绩相同的成绩的同学;然后限制该同学是学习数据库的学生。
最终的正确结果。
--16 right
select student.Stu_id,Stu_name,Depar_name
from Student,StudentGrade,Class,Deparment,course
where Course_name='数据库'
and course.Course_id=StudentGrade.Course_id
and class.Class_id= Student.Class_id
and class.Depar_id=Deparment.Depar_id
and student.Stu_id=StudentGrade.Stu_id
and grade = (select max(grade)
from studentgrade,course
where Course_name='数据库'
and course.Course_id=StudentGrade.Course_id)
17.至少选修了两门课及以上的学生姓名和性别。
第一张是我的是我的实验结果,第二张是老师提供的代码的实验结果。两个结果都是一样的。如下为两份不同的代码:
我的:
--17
selectStu_name,Stu_sex
from student,StudentGrade
where student.Stu_id=StudentGrade.Stu_id
group by studentGrade.Stu_id , student.stu_id,Stu_name,Stu_sex
having count(*)>=2
老师的:
select stu_name,stu_sex
from student
where stu_id in (select stu_id
from studentgrade
group by stu_id
having count(*)>=2)
总结分析:
个人更加偏向于老师的代码。
老师使用的是嵌套的方法。
在嵌套里面在进入元组的划分group,——顺便提及一下做了那么多关于group的实验,我发现group的划分尽量是主属性这可以唯一表示该元组信息的。
我的代码是先直接连接再group,这就比较麻烦多了因为需要划分的对象多了。
18.检索既选修课程“数据结构”又选修了“C语言”的学生学号。
这是我的错误实验结果。什么都没有显示。我的思路有问题,需要重新推翻。
一个元组不可能同时等于C语言和数据结构,所以这个是空的。那么使用嵌套查询可能会好一点。
--18 error_1
select Stu_id
from Student
where Stu_id in(select Stu_id
from StudentGrade
where Course_id in(select Course_id
from course
where Course_name in('C语言','数据结构')))
还是存在蛮大的误差的。这个代码是查询选修的C语言或数据结构的学生的代码。这个和题意不符合。我想那么把最后的一个嵌套拆开会是怎么样的呢?
这回的实验结构就比较满意咯。
--18 right
select Stu_id
from Student
where Stu_id in(select Stu_id
from StudentGrade
where Course_id in(select Course_id
from course
where Course_name ='C语言'))
and stu_id in(select Stu_id
from StudentGrade
where Course_id in(select Course_id
from course
where Course_name ='数据结构'))
19.检索选修了‘0103’和‘0105’两门课程,并且‘0103’这门课程成绩高于‘0105’的学生的学号。
这道题目一开始没有太多头绪,参考老师的代码发现可以使用自身连接。
--19
select x.stu_id
from StudentGrade x,StudentGrade y
where x.Stu_id=y.Stu_id and x.Course_id='0103' and y.Course_id='0105' and x.Grade>y.Grade
回归到18题,是不是也可以使用自身连接呢?
这个也是可以的。正如老师说的实现方法有很多。
--18 try 自我连接
select x.Stu_id
from StudentGrade x,StudentGrade y
where x.Course_id in (select Course_id
from course
where Course_name ='C语言') and y.Course_id in (select Course_id
from course
where Course_name ='数据结构') and x.Stu_id=y.Stu_id
20.检索选修了课程“数据结构”和“C语言”两门课程并且“数据结构”分数高于“C语言”的学生学号和姓名。
20题其实就是在19的基础上修改一点,两者还是十分相像的。
上图是老师给的答案。这是有缺漏的,没有学生的姓名只有学号?!看来还是靠自己吧。
--20
select x.stu_id,Stu_name
from StudentGrade x,StudentGrade y,Student
where x.Course_id in (select Course_id
from course
where Course_name ='C语言')
and y.Course_id in (select Course_id
from course
where Course_name ='数据结构')
and x.Stu_id=y.Stu_id
and x.Grade>y.Grade
and student.Stu_id=x.Stu_id
列出所有班名、班主任、班长、系名。
(请使用连接查询;
进一步考虑使用外连接,因为很多班级可能是没有班长的,考虑需要显示所有班级的信息)
外连接可以参考课本P102 3.外连接
--21 外连接
select Class_name,Director,Monitor,Depar_name
from class left outer join Deparment on(Class.Depar_id=Deparment.Depar_id)
三、实验小结
1.思考简单查询、连接查询与嵌套查询有什么不同?连接查询与嵌套查询有何区别与联系?
Q1:
简单查询一般是在一个表中,通过简单的查询选择所需要的数据;连接查询,有等值与非等值连接外连接内连接等等,多个关系表,通过操作串联起来成为一个新表;嵌套查询是将多个表通过嵌套的方式进行查询,先进行最内的表查询,再一步步向最外层嵌套迈进
Q2:
连接查询与嵌套查询都是将多个表联系起来进行程序,只是实现的方式有所不同,有些嵌套查询,可以通过连接查询代替,但是有些就不能代替
各位帅气漂亮的大大们
你懂得
十八【殷勤脸】