实验二 SQL Server的数据查询

实验目的:

1.掌握基本的查询、嵌套子查询及连接查询

2.学习数据库保留字符的使用。

3.学习部分统计函数的使用。

实验要求:

1.熟练掌握基本的查询、嵌套子查询及连接查询

2.体会各种查询的异同及相互之间的转换,体会各种查询的执行过程,为综合应用打下良好的基础。

 实验环境及学时安排:

1.SQL SERVER2008

2.学时:6学时

实验内容:

实验问题描述:

某学院有若干班级,每个班级有若干学生;学院每年每学期都开设有若干门课程;每门课程有多个学生选修,每个学生每学期可以同时选修多门课程,每个学生对于同一门课程可以多次选修,但每学期只能选修1次,课程选修成绩以综合成绩记录。请设计某学院简单的教学管理系统的E-R模型,要求给出每个实体、联系的属性。根据以上语义,我们可得了上图1如示的教学管理系统E-R图(属性未画出)。

根据学院提供的学生选课及其他的部分数据,将上图1所示的E-R图中的部分实体和联系转换为关系,得到如下5个关系模式和相应的数据字典描述。

A、关系模式

⑴ 班级:包括班级号、班级名、所属学院、年级、班级人数;

⑵ 学生:包括学号、姓名、性别、出生日期、籍贯、民族、所属班级;

⑶ 课程:包括课程编号、课程名称、学分、学时数、先修课程;

⑷ 学期:包括学期号、学期名、备注。

⑸ 成绩:包括学号、课程编号、学期、成绩。

B、数据字典

表名

中文名

Class

班级

Student

学生

Course

课程

Term

学期

Score

成绩

班级:Class

字段名

数据类型

可空性

主键

外键

默认值

字段含义

classNo

char(6)

NOT NULL

Yes

No

班级号

className 

varchar(30)

NOT NULL

unique

No

班级名

institute 

char(30)

NOT NULL

No

No

所属学院

grade

smallint

NOT NULL

No

No

0

年级

classNum

tinyint

NULL

No

No

班级人数

学生:Student

字段名

数据类型

可空性

主键

外键

默认值

字段含义

studentNo

char(7)

NOT NULL

Yes

No

学生学号

StudentName

varchar(20)

NOT NULL

No

No

学生姓名

sex

char(2)

NULL

No

No

性别

birthday

datetime

NULL

No

No

出生日期

native

varchar(20)

NULL

No

No

籍贯

nation

varchar(30)

NULL

No

No

汉族

民族

classNo

char(6)

NULL

No

Yes

所属班级

约束条件:

学生学号为7位数字字符;

所属班级classNo参照表Class表的classNo。

课程:Course

字段名

数据类型

可空性

主键

外键

默认值

字段含义

courseNo

char(3)

NOT NULL

Yes

No

课程号

courseName

varchar(30)

NOT NULL

unique

No

课程名

creditHour

numeric(1)

NOT NULL

No

No

0

学分

creditHourse

tinyint

NOT NULL

No

No

学时

priorCourse

char(3)

NULL

No

Yes

先修课程

约束条件:

先修课程priorCourse参照表Course表的courseNo。

学生选课:Term

字段名

数据类型

可空性

主键

外键

默认值

字段含义

TermNo 

char(3)

NOT NULL

Yes

No

学期号

termName

varchar(30)

NOT NULL

No

No

学期名

remarks

varchar(10)

NULL

No

No

备注

成绩:Score

字段名

数据类型

可空性

主键

外键

默认值

字段含义

studentNo

char(7)

NOT NULL

Yes

Yes

学号

courseNo

char(3)

NOT NULL

Yes

Yes

课程号

termNo

char(3)

NOT NULL

Yes

Yes

学期号

score

NUMERIC(5,1)

NULL

No

No

综合成绩

约束条件:

综合成绩为百分制成绩;

学号、课程号和学期号一起构成主码;

学号studentNo参照表student表的studentNo;

课程号courseNo参照表course表courseNo;

学期号termNo参照表Term表的termNo

设计任务

一、创建ScoreDB数据库

利用实验给出的“ScoreDB.sql”脚本文件,完成scoreDB数据库及对象的创建、表对象中数据记录的插入等操作。

二、针对创建好的ScoreDB数据库,完成下列要求的查询操作

1.投影查询:

  1. 查询Student表中所有学生的studentNo、studentName和Sex,并在查询结果中将列名显示为:学号、姓名和性别。

SQL语句如下:

运行结果

2.单表查询:

  1. 查询SCore表中成绩在60到80之间的所有记录。

   SQL语句如下:

运行结果:

  1. 查询成绩低于60分或高于90分的学生学号。(提示:用NOT BETWEEN AND

   SQL语句如下:

运行结果:

  1. 查询所有姓王且籍贯为“南昌”的学生姓名。

   SQL语句如下:

运行结果:

  1. 查询SCore表中成绩为85、86、88或90的记录。

   SQL语句如下:

运行结果:

  1. 查询年龄小于22岁或蒙古族的学生姓名。

   SQL语句如下:

  1. 查询选修了课程但没有参加考试的学生学号。

   SQL语句如下:

3.对查询结果排序:

  1. 查询Score表中的所有记录,并且以CourseNo升序、Score降序显示。

   SQL语句如下:

4.使用聚合函数:

  1. 统计Student表中汉族学生人数。

   SQL语句如下:

运行结果:

  1. 统计Student表有多少个姓(假设所有姓氏均为单姓)。

   SQL语句如下:

运行结果:

  1. 统计 “002”号课程的平均分。

   SQL语句如下:

运行结果:

5.数据分组:

  1. 查询选修人数大于2人,并且平均分在80分以上的课程号。

   SQL语句如下:

  1. 查询至少有两门课程的成绩在80分以上学生的学号。

   SQL语句如下:

6.表的连接查询:

  1. 查询至少选修了两门以上课程的学生的学号、姓名和所在班级。

   SQL语句如下:

运行结果:

  1. 查询所有学生(包括未选课的学生)的学号、姓名(SName)及该学生所选课程的平均分。提示:用外连接

   SQL语句如下:

运行结果:

7.嵌套查询:(以下部分必须用嵌套查询来完成)

  1. 查询“刘晨”班上同学的学号和姓名。

   SQL语句如下:

运行结果:

  1. 查询修选了“高等数学”课程的学生学号和姓名。

   SQL语句如下:

运行截图:

  1. 查询选修学生人数少于3人的课程名称。

   SQL语句如下:

运行结果:

  1. 查询成绩低于该门课程的平均分的学生的学号。

   SQL语句如下:

运行结果:

  1. 查询所有学分为6的全部课程的学生姓名。

   SQL语句如下:

运行结果:

  1. 查询“cS1601”班同学都选修的课程名称

   SQL语句如下:

运行结果:

  1. 查询选修了所有课程的学生的学号,姓名,年龄

运行结果:

  1. 查询没有选修课程的学生姓名。

   SQL语句如下:

运行结果:

8.集合操作:(必须通过集合的交、并、差实现)

  1. 查询至少选修两门以上课程(包括两门)的学生学号。

   SQL语句如下:

运行结果:

  1. 查询没有选修课程的学生姓名。

   SQL语句如下:

运行结果:

9视图的定义及其操作

  1. 定义一个查询学生的学号、姓名、学期、最高成绩、最低成绩、平均成绩的视图studentScore。

   SQL语句如下:

运行结果:

  1. 通过视图studentScore查询最高成绩在90分以上(含90分)且没有不及格成绩的学生学号、姓名、系名、班级。

   SQL语句如下:

运行结果:

#	查询Student表中所有学生的studentNo、studentName和Sex,并在查询结果中将列名显示为:学号、姓名和性别。
SELECT studentNo,studentName,Sex FROM student;
#	查询SCore表中成绩在60到80之间的所有记录。
SELECT * FROM score WHERE score BETWEEN 60 AND 80;
#	查询成绩低于60分或高于90分的学生学号
SELECT studentNo FROM score WHERE score NOT BETWEEN 60 AND 90;
#	查询所有姓王且籍贯为“南昌”的学生姓名
SELECT studentName FROM student WHERE studentName LIKE '王%' AND native = '南昌';
#	查询SCore表中成绩为85、86、88或90的记录
SELECT * FROM score WHERE score IN (85,86,88,90);



#*******	查询年龄小于22岁或蒙古族的学生姓名
SELECT * FROM student WHERE birthday > DATE_SUB(DATE('2020-05-26'),INTERVAL 22 YEAR) OR nation = '蒙古族';
SELECT studentName FROM student WHERE TIMESTAMPDIFF(YEAR,birthday,'2020-10-01') < 22 OR nation = '蒙古族';
#	查询选修了课程但没有参加考试的学生学号
SELECT studentNo FROM score WHERE score IS NULL;
#	查询Score表中的所有记录,并且以CourseNo升序、Score降序显示。
SELECT * FROM score ORDER BY CourseNo ASC,Score DESC;
#		统计Student表中汉族学生人数。
SELECT COUNT(*) FROM student WHERE nation = '汉族';


#********	统计Student表有多少个姓(假设所有姓氏均为单姓)。
SELECT COUNT(DISTINCT LEFT(studentName,1))  FROM student; 
SELECT DISTINCT SUBSTR(studentName,1,1) FROM student;
#	统计 “002”号课程的平均分。
SELECT AVG(score) FROM score WHERE courseNo = 002;
#	查询选修人数大于2人,并且平均分在80分以上的课程号。
SELECT courseNo FROM  score GROUP BY courseNo HAVING COUNT(*) > 2 and AVG(score) > 80; 

#**********	查询至少有两门课程的成绩在80分以上学生的学号。
#ERRORS:1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'scoredb.score.courseNo' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
# SELECT studentNo,courseNo,COUNT(*) coursenumber FROM score GROUP BY studentNo HAVING coursenumber >=2 AND score >=80;
# count(*) 无法和其他未被统计或者分组的字段名同时打印出来,报错编号1055,解决:写在having后面作为条件筛选
SELECT studentNo FROM score WHERE score >= 80 GROUP BY studentNo HAVING  COUNT(*) >=2;

#******	查询至少选修了两门以上课程的学生的学号、姓名和所在班级。
#SELECT studentNo,COUNT(*) number1  FROM score GROUP BY studentNo HAVING number1 >=2;
-- SELECT DISTINCT s.studentName,c.studentNo,s.classNo FROM student AS s ,score AS c WHERE s.studentNo = c.studentNo; 
#内连接(inner join):取出两张表中匹配到的数据,匹配不到的不保留
#外连接(outer join):取出连接表中匹配到的数据,匹配不到的也会保留,其值为NULL

SELECT student.studentNo AS 学号, student.studentName AS 姓名, class.className 
FROM ( student INNER JOIN score ON student.studentNo = score.studentNo )
INNER JOIN class ON student.classNo = class.classNo
GROUP BY student.studentNo
HAVING COUNT(*) >= 2;

#	查询所有学生(包括未选课的学生)的学号、姓名(SName)及该学生所选课程的平均分。提示:用外连接
#SELECT studentName,studentNo,AVG(score) FROM student AS s ,score AS c  GROUP  BY studentNo 1052 - Column 'studentNo' in field list is ambiguous
SELECT student.studentName,student.studentNo,AVG(score.score) 
FROM student  LEFT JOIN score ON student.studentNo = score.studentNo
GROUP  BY student.studentNo 

#	查询“刘晨”班上同学的学号和姓名。
SELECT studentNo,studentName FROM student WHERE classNo = (SELECT classNo FROM student WHERE studentName = '刘晨');

#	查询修选了“高等数学”课程的学生学号和姓名。(嵌套查询)
SELECT DISTINCT student.studentNo,student.studentName 
FROM student INNER JOIN score ON student.studentNo = score.studentNo
WHERE courseNo = (SELECT courseNo FROM course WHERE courseName = '高等数学');
#最好将=换为in,满足其一即可,包括唯一的情况

-- SELECT DISTINCT student.studentNo,student.studentName 
-- FROM student
-- WHERE studentNo 
-- = (select studentNo 
-- FROM score 
-- WHERE courseNo = (SELECT courseNo FROM course WHERE courseName = '高等数学'));
#mysql错误:Subquery returns more than 1 row  解决:在子查询前加any关键字

SELECT DISTINCT student.studentNo,student.studentName 
FROM student
WHERE studentNo 
= ANY(select studentNo 
FROM score 
WHERE courseNo = (SELECT courseNo FROM course WHERE courseName = '高等数学'));

#	查询选修学生人数少于3人的课程名称。
SELECT courseName 
FROM course 
WHERE courseNo = (SELECT courseNo FROM score GROUP BY courseNo HAVING COUNT(*) <= 3 );

#	查询所有学分为6的全部课程的学生姓名。
SELECT DISTINCT studentName
FROM student 
WHERE studentNo 
= ANY(select studentNo 
FROM score
WHERE courseNo = (SELECT courseNo FROM course WHERE creditHour = 6));

SELECT DISTINCT studentName
FROM student INNER JOIN score ON student.studentNo = score.studentNo

WHERE courseNo = (SELECT courseNo FROM course WHERE creditHour = 6);

#	查询“cS1601”班同学都选修的课程名称
SELECT course.courseName 
FROM course INNER JOIN score ON course.courseNo = score.courseNo
GROUP BY score.courseNo 
HAVING COUNT(*) =(SELECT COUNT(*) FROM student WHERE classNo = 'cS1601'); 

#	查询选修了所有课程的学生的学号,姓名,年龄
SELECT student.studentNo,student.studentName,TIMESTAMPDIFF(YEAR,birthday,CURDATE())
FROM student INNER JOIN score ON student.studentNo = score.studentNo
GROUP BY score.studentNo
HAVING COUNT(*) =(SELECT COUNT(*) FROM course );

#	查询没有选修课程的学生姓名。
SELECT studentName
FROM student
WHERE studentNo IN (SELECT student.studentNo FROM student WHERE student.studentNo NOT IN (SELECT studentNo FROM score));

SELECT a.* from
(select studentNo 
From student
union all 
select studentNo
From score
GROUP BY studentNo
Having Count(*) > 2) as a

#   查询至少选修两门以上课程(包括两门)的学生姓名。
SELECT studentName FROM student 
WHERE studentNo IN 
(select studentNo 
FROM score
GROUP BY studentNo
HAVING COUNT(*) >= 2);

#	查询没有选修课程的学生姓名。
SELECT studentName
FROM student
WHERE studentNo IN (SELECT student.studentNo FROM student WHERE student.studentNo NOT IN (SELECT studentNo FROM score));






#******	定义一个查询学生的学号、姓名、学期、最高成绩、最低成绩、平均成绩的视图studentScore。
#GROUP BY score.studentNo 单个分组不正确?
#1054 - Unknown column 'term.termNo,student.studentName' in 'group statement'  有中文符号
#1055 - Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'scoredb.term.termName' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
#在SELECT中的列,没有在GROUP BY中出现,那么将认为这个SQL是不合法的,因为列不在GROUP BY从句中,即只能展示group by的字段,其他均都要报1055的错;

CREATE VIEW studentScore AS
SELECT student.studentNo AS 学号,
student.studentName,
term.termName,
avg(score),
max(score),
MIN(score)
FROM (student INNER JOIN score ON student.studentNo = score.studentNo)
INNER JOIN term ON score.termNo = term.termNo
GROUP BY score.studentNo,term.termNo,student.studentName;

# 通过视图studentScore查询最高成绩在90分以上(含90分)且没有不及格成绩的学生学号、姓名、系名、班级。

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值