我从前最怕旁人火眼金睛,如今,倒是盼着有人能够洞幽烛远。如此,就能赠我一点欢喜。
实验2 数据查询
一、实验目的
熟悉SQL语句的数据查询语言,能够使用SQL语句对数据库进行单表查询、连接查询、嵌套查询、集合查询和统计查询。通过实验理解在数据库表中对数据的BULL值的处理。
二、实验内容1
1. 问题描述
要求:
以schoo!数据库为例,在该数据库中存在4张表格,分别为:
STUDENTS(sid,sname,email,grade)
、、、
TEACHERS(tid,tname,email,salary)
、、、
COURSES(cid,cname,hour)
、、、
CHOICES(no,sid,tid,cid,score)
、、、
在数据库中,存在这样的关系:学生可以选择课程。一个课程对应一个教师。在CHOICES中保存学生的选课记录。
按以下要求对数据库进行查询操作:
(1)查询年级为2001的所有学生的名称,按编号升序排列。
(2)查询学生的选课成绩合格的课程成绩,并把成绩换算为积点(60分对应积点为1
每增加1分,积点增加0.1)。
(3)查询课时是48或64的课程的名称。
(4)查询所有课程名称中含有data的课程编号。
(5)查询所有选课记录的课程号(不重复显示)。
(6)统计所有老师的平均工资。
(7)查询所有学生的编号,姓名和平均成绩,按总平均成绩降序排列。
(8)统计各个课程的选课人数和平均成绩。
(9)查询至少选修了三门课程的学生编号。
(10)查询编号800009026的学生所选的全部课程的课程名和成绩。
(11)查询所有选了database的学生的编号。
(12)求出选择了同一个课程的学生数。
(13)求出至少被两名学生选修的课程编号。
2. 数据库设计
本节内容主要是对数据库进行查询操作,包括如下4类查询方式。
1)单表查询
•查询的目标表达式为所有列、指定列或指定列的运算。
•使用 DISTINCT保留字消除重复行。
•对查询结果排序和分组。
•集合分组使用集函数进行各项统计。
一般格式:
SELECT [ALL|DISTINCT] <目标列表达式>
[,<目标列表达式>] …
FROM <表名或视图名>[, <表名或视图名> ] …
[ WHERE <条件表达式> ]
[ GROUP BY <列名1> [ HAVING <条件表达式> ] ]
[ ORDER BY <列名2> [ ASC|DESC ] ];
2) 连接查询
•笛卡儿连接和等值连接。
自连接。
•外连接。
•复合条件连接。
•多表连接。
一般格式:
[<表名1>.]<列名1> <比较运算符> [<表名2>.]<列名2>
[<表名1>.]<列名1> BETWEEN [<表名2>.]<列名2> AND [<表名2>.]<列名3>
连接字段:连接谓词中的列名称
连接条件中的各连接字段类型必须是可比的,但名字不必是相同的
3. 程序实现及测试
(1)查询年级为2001的所有学生的名称,按编号升序排列。
程序:
select sname
from STUDENTS
where grade='2001'
order by sid;
结果: 、、、、、、
(2)查询学生的选课成绩合格的课程成绩,并把成绩换算为积点(60分对应积点为1每增加1分,积点增加0.1)。
程序:
select (score-60)*0.1+1
from CHOICES
where score>=60;
结果: 、、、、、、
(3)查询课时是48或64的课程的名称。
程序:
select cname
from COURSES
where hour=48 or hour=64;
结果:
(4)查询所有课程名称中含有data的课程编号。
程序:
select cid
from COURSES
where cname like '%data%';
结果:
(5)查询所有选课记录的课程号(不重复显示)。
程序:
select distinct cid
from CHOICES;
结果: 、、、、、、
(6)统计所有老师的平均工资。
程序:
select AVG(salary)
from TEACHERS;
结果:
(7)查询所有学生的编号,姓名和平均成绩,按总平均成绩降序排列。
程序:
select STUDENTS.sid,sname,AVG(score)
from CHOICES,STUDENTS
where CHOICES.sid=STUDENTS.sid
group by STUDENTS.sid,sname
order by AVG(score) desc
结果: 、、、、、、
(8)统计各个课程的选课人数和平均成绩。
程序:
select COUNT(distinct sid),AVG(score)
from CHOICES
group by cid;
结果: 、、、、、、
(9)查询至少选修了三门课程的学生编号。
程序:
select STUDENTS.sid
from STUDENTS,CHOICES
where(
STUDENTS.sid=CHOICES.sid and STUDENTS.sid in(
select sid
from CHOICES
group by sid
having COUNT(cid)>=3
)
);
结果: 、、、、、、
(10)查询编号800009026的学生所选的全部课程的课程名和成绩。
程序:
select cname,score
from COURSES,CHOICES
where CHOICES.cid=COURSES.cid and CHOICES.sid='800009026';
结果:
(11)查询所有选了database的学生的编号。
程序:
select distinct sid
from CHOICES,COURSES
where CHOICES.cid in(
select cid
from COURSES
where cname='database'
);
结果: 、、、、、、
(12)求出选择了同一个课程的学生数。
程序:
select cid,COUNT(*)
from CHOICES
group by cid;
结果: 、、、、、、
(13)求出至少被两名学生选修的课程编号。
程序:
select cid
from CHOICES
group by cid
having COUNT(*)>=2;
结果: 、、、、、、
三、实验内容2
1. 问题描述
要求:
以schoo!数据库为例,在该数据库中存在4张表格,分别为:
STUDENTS(sid,sname,email,grade)
TEACHERS(tid,tname,email,salary)
COURSES(cid,cname,hour)
CHOICES(no,sid,tid,cid,score)
在数据库中,存在这样的关系:学生可以选择课程。一个课程对应一个教师。在CHOICES中保存学生的选课记录。
按以下要求对数据库进行查询操作:
(14)查询选修了编号80009026的学生所选的某个课程的学生编号。
(15)查询学生的基本信息及选修课程编号和成绩。
(16)查询学号850955252的学生的姓名和选修的课程名称及成绩。
(17)查询学号850955252的学生同年级的所有学生资料。
(18)查询所有的有选课的学生的详细信息。
(19)查询没有学生选的课程的编号。
(20)查询选修了课程名为C++的学生学号和姓名。
(21)找出选修课程成绩最差的选课记录。
(22)找出和课程UML或课程C++的课时一样的课程名称。
(23)查询所有选修编号10001的课程的学生的姓名。
(24)查询选修了所有课程的学生姓名。
(25)利用集合运算,查询选修课程C++或课程Java的学生的编号。
(26)实现集合交运算,查询既选修课程C++又选修课程Java的学生的编号。
(27)实现集合减运算,查询选修课程C++而没有选修课程Java的学生的编号。
2. 数据库设计
3) 嵌套查询
•通过实验验证对子查询的两个限制条件。
•体会相关子查询和不相关自查询的不同。
•考察4类谓词的用法,包括:
第1类,IN,NOT IN;
第2类,带有比较运算符的子查询;
第3类,SOME,ANY 或ALL谓词的子查询;
第4类,带有EXISTS谓词的子查询。
一般结构:
一个SELECT-FROM-WHERE语句称为一个查询块
将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询
SELECT Sname /*外层查询/父查询*/
FROM Student
WHERE Sno IN
(SELECT Sno /*内层查询/子查询*/
FROM SC
WHERE Cno= ' 2 ');
4) 集合运算
•使用保留字 UNION进行集合或运算。
•采用逻辑运算符AND或 OR来实现集合交和减运算。
种类及注意:
并操作UNION
交操作INTERSECT
差操作EXCEPT
参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同
3. 程序实现及测试
(14)查询选修了编号80009026的学生所选的某个课程的学生编号。
程序:
select cid,sid
from CHOICES
where sid='80009026';
结果:
(15)查询学生的基本信息及选修课程编号和成绩。
程序:
select STUDENTS.sid,sname,email,grade,cname,score
from STUDENTS,COURSES,CHOICES
where STUDENTS.sid=CHOICES.sid and COURSES.cid=CHOICES.cid;
结果:
、、、、、、
(16)查询学号850955252的学生的姓名和选修的课程名称及成绩。
程序:
select sname,cname,score
from STUDENTS,COURSES,CHOICES
where STUDENTS.sid='850955252' and CHOICES.sid='850955252' and COURSES.cid=CHOICES.cid;
结果:
(17)查询学号850955252的学生同年级的所有学生资料。
程序:
select *
from STUDENTS
where grade in(
select grade
from STUDENTS
where sid='850955252'
);
结果: 、、、、、、
(18)查询所有的有选课的学生的详细信息。
程序:
select *
from STUDENTS
where sid in(
select sid
from CHOICES
);
结果: 、、、、、、
(19)查询没有学生选的课程的编号。
程序:
select cid
from COURSES
where cid not in(
select cid
from CHOICES
);
结果:
(20)查询选修了课程名为C++的学生学号和姓名。
程序:
select STUDENTS.sid,sname
from STUDENTS,COURSES,CHOICES
where STUDENTS.sid=CHOICES.sid and COURSES.cid=CHOICES.cid and cname='C++';
结果: 、、、、、、
(21)找出选修课程成绩最差的选课记录。
程序:
select *
from CHOICES
where score in(
select min(score)
from CHOICES
);
结果:
、、、、、、
(22)找出和课程UML或课程C++的课时一样的课程名称。
程序:
select cname
from COURSES
where hour in(
select hour
from COURSES
where cname='UML' or cname='C++'
);
结果:
(23)查询所有选修编号10001的课程的学生的姓名。
程序:
select sname
from STUDENTS
where sid in(
select sid
from COURSES
where cid='10001'
)
结果: 、、、、、、
(24)查询选修了所有课程的学生姓名。
程序:
select sname
from STUDENTS
where not exists(
select *
from COURSES
where not exists(
select *
from CHOICES
where sid=STUDENTS.sid and cid=COURSES.cid
)
)
结果:
(25)利用集合运算,查询选修课程C++或课程Java的学生的编号。
程序:
select sid
from CHOICES
where sid in(
select sid
from COURSES
where cname='C++'
)
union
select sid
from CHOICES
where sid in(
select sid
from COURSES
where cname='Java'
)
结果: 、、、、、、
(26)实现集合交运算,查询既选修课程C++又选修课程Java的学生的编号。
程序:
select sid
from CHOICES
where sid in(
select sid
from COURSES
where cname='C++'
)
intersect
select sid
from CHOICES
where sid in(
select sid
from COURSES
where cname='Java'
)
结果: 、、、、、、
(27)实现集合减运算,查询选修课程C++而没有选修课程Java的学生的编号。
程序:
select sid
from CHOICES
where sid in(
select sid
from COURSES
where cname='C++'
)
except
select sid
from CHOICES
where sid in(
select sid
from COURSES
where cname='Java'
)
结果: