一、实验名称和性质
子查询
验证 设计
二、实验目的
1.掌握子查询的嵌套查询;
2.掌握集合操作
3.了解EXISTS嵌套查询方法;
三、实验的软硬件环境要求
硬件环境要求:
PC机(单机)
使用的软件名称、版本号以及模块:
Windows10,SQLServer2019
四、知识准备
- 嵌套子查询
SELECT <目标列表达式列表>
FROM 表名
WHERE 列名IN
(SELECT 字句)
2.集合运算—union(并集)、intersect(交集)和except(差集)& with as
3.EXISTS嵌套子查询
–带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。
●若内层查询结果非空,则返回真值
●若内层查询结果为空,则返回假值。
由EXISTS引出的子查询,其目标列表达式通常都用* ,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义
所以,EXISTS子查询中一般是相关自查询,即子查询脱离父查询后不能单独执行。
思考:如果EXISTS子查询中是不相关子查询,会有什么结果?
五、实验内容
1.子查询嵌套;
2.集合运算
3EXISTS嵌套查询。
六、验证性实验
(表和表中的数据,见实验6,XXX为学号的后两位)
(1)查询与’王丽娜’同班的学生学号,姓名
SELECT SNO, sname FROM STUDENT WHERE CLASS=(SELECT CLASS FROM STUDENT WHERE SNAME='王丽娜')
SELECT S1.SNO,s1.Sname FROM STUDENT AS S1, STUDENT AS S2
WHERE S1.CLASS=S2.CLASS AND S2.SNAME='王丽娜'
SELECT S1.SNO,s1.Sname FROM STUDENT AS S1 JOIN STUDENT AS S2
ON S1.CLASS=S2.CLASS WHERE S2.SNAME='王丽娜'
(2)显示每个学生的非最高分成绩(学生自己的选课成绩中,不是最高分的选课记录显示出来)
SELECT SNO,CNO,DEGREE FROM SCOREXXX ASSC1
WHERE DEGREE<(SELECT MAX(DEGREE) FROM SCOREXXX ASSC2
WHERE SC2.SNO=SC1.SNO)
显示每个学生的最高分成绩(学生自己的选课成绩中,最高分的选课记录显示出来)
SELECT SNO, CNO, DEGREE FROM SCOREXXX AS SC1
WHERE DEGREE =(SELECT MAX(DEGREE) FROM SCOREXXX AS SC2
WHERE SC2.SNO=SC1.SNO)
显示各科的最高分的学号,姓名及课程名和成绩
(3)查询’操作系统’课程的选课人数
SELECT COUNT(*) FROM SCOREXXX
WHERE CNO IN--IN 可以换为=
(SELECT CNO FROM COURSEXXX WHERE CNAME='操作系统')
(4) 相关的子查询:子查询中要用到父查询表的信息,子查询不能独立执行。
如,查询选修课程号为“3-105”课程且成绩至少高于选修课程号为“3-245”的同学的Cno、Sno和DEGREE。
在子查询中,因为要查找该同学’3-245’课程的成绩,所以,需要父查询表中该学生的学号信息。
SELECT CNO,SNO,DEGREE FROM SCOREXXXAS SC1
WHERE CNO='3-105'AND DEGREE >(
SELECT DEGREE FROM SCOREXXXAS SC2
WHERE SC2.SNO=SC1.SNO AND SC2.CNO='3-245')
SELECT CNO,SNO,DEGREE CJ105,(SELECT DEGREE FROM SCOREXXXAS SC2
WHERE SC2.SNO=SC1.SNO AND SC2.CNO='3-245') CJ245 FROM SCOREXXXAS SC1 WHERE CNO='3-105'AND DEGREE >(
SELECT DEGREE FROM SCOREXXXAS SC2
WHERE SC2.SNO=SC1.SNO AND SC2.CNO='3-245')
(5)EXISTS嵌套子查询,分析以下语句
SELECT SNO,SNAME FROM STUDENTXXX S
WHERE EXISTS (SELECT * FROM SCOREXXX WHERE SNO=S.SNO)
SELECT SNO,SNAME FROM STUDENTXXX S
WHERE not EXISTS (SELECT * FROM SCOREXXX WHERE SNO=S.SNO)
SELECT SNO,SNAME FROM STUDENTXXX S
WHERE EXISTS (SELECT * FROM SCOREXXX WHERE SNO=‘111’)
SELECT SNO,SNAME FROM STUDENTXXX S
WHERE EXISTS (SELECT * FROM SCOREXXX WHERE SNO=‘108’)
(6)union,分析以下语句
Select tName,tSex from teacherXXX
union
select sName,sSex from STUDENTXXX
select tName from teacherXXX WHERE TNAME LIKE '李%'
union
select sName from STUDENTXXX WHERE sNAME LIKE '李%'
select tName from teacherXXX WHERE TNAME LIKE '李%'
union ALL
select sName from STUDENTXXX WHERE sNAME LIKE '李%'
(7)intersect(交集)集合运算,分析以下语句
select * from STUDENTXXX WHERE sno<‘108'
intersect
select * from STUDENTXXX WHERE sno>‘103'
(8)except(差集)集合运算,分析以下语句
select * from STUDENTXXX WHERE sno<‘108'
except
select * from STUDENTXXX WHERE sno>‘103'
(9)子查询作为表
Select s.*,av from STUDENTXXX sjoin(select sno,avg(degree)av from SCOREXXX groupbysno)tons.sno=t.sno
(10)其他
- Select row_number()over(orderbysno)asrowNum,* from SCOREXXX
- Select row_number()over(partitionbysnoorderbysno)asrowNum,* from SCOREXXX
- select sno,cno,casewhendegree>=90then'A'
WHENDEGREE>=80THEN'B'
WHENDEGREE>=70THEN'C'
WHENDEGREE>=60THEN'D'
ELSE'E'
END
FROM SCOREXXX
- select sno,sname,case ssex when '男' then 'M'
when '女' then 'F'
END XB
from STUDENTXXX
- SELECT * into STU_XXX FROM STUDENTXXX WHERE SSEX=‘男’
- INSERT STU_XXX SELECT * FROM STUDENTXXX WHERE SSEX=‘女’
七、设计性实验
1.实验内容(用子查询完成)
- 查询每人的成绩(学号、课程号、成绩)和所有成绩平均分;
SELECT
S.Sno,
SC.Cno,
SC.Degree,
(SELECT AVG(Degree) FROM Score023) AS AvgAllScore
FROM
Student023 S
JOIN
Score023 SC ON S.Sno = SC.Sno;
- 查询每人的成绩(学号、课程号、成绩)和本课程平均分;
SELECT
S.Sno,
SC.Cno,
SC.Degree,
AVG(SC2.Degree) OVER(PARTITION BY SC.Cno) AS AvgCourseScore
FROM
Student023 S
JOIN
Score023 SC ON S.Sno = SC.Sno
JOIN
Score023 SC2 ON SC.Cno = SC2.Cno;
- 查询每人的成绩(学号、姓名,课程名、成绩)和本班总平均分;
SELECT
S.Sno,
S.Sname,
C.Cname,
SC.Degree,
(SELECT AVG(SC2.Degree)
FROM Score023 SC2
JOIN Student023 S2 ON SC2.Sno = S2.Sno
WHERE S2.Class = S.Class) AS ClassAvgScore
FROM
Student023 S
JOIN
Score023 SC ON S.Sno = SC.Sno
JOIN
Course023 C ON SC.Cno = C.Cno;
- 查询每人的成绩(学号、姓名,课程名、成绩)和本班本科平均分;
SELECT
S.Sno,
S.Sname,
C.Cname,
SC.Degree,
(SELECT AVG(SC2.Degree)
FROM Score023 SC2
JOIN Student023 S2 ON SC2.Sno = S2.Sno
WHERE S2.Class = S.Class AND SC2.Cno = SC.Cno) AS ClassCourseAvg
FROM
Student023 S
JOIN
Score023 SC ON S.Sno = SC.Sno
JOIN
Course023 C ON SC.Cno = C.Cno;
- 查询成绩高于学号为“101”的课程号为“3-105”的成绩的所有记录。
SELECT *
FROM Score023
WHERE Degree > (
SELECT Degree
FROM Score023
WHERE Sno = '101' AND Cno = '3-105'
);
- 查询和学号为101的同学同月出生的所有学生的Sno、Sname和Sbirthday列。
SELECT
Sno, Sname, Sbirthday
FROM
Student023
WHERE
MONTH(Sbirthday) = (
SELECT MONTH(Sbirthday)
FROM Student023
WHERE Sno = '101'
);
- 查询“张旭“教师任课的学生成绩(学号、姓名,课程名、成绩)。
SELECT
S.Sno,
S.Sname,
C.Cname,
SC.Degree
FROM
Student023 S
JOIN
Score023 SC ON S.Sno = SC.Sno
JOIN
Course023 C ON SC.Cno = C.Cno
JOIN
Teacher023 T ON C.Tno = T.Tno
WHERE
T.Tname = '张旭';
- 查询每科的最高分信息(学号、姓名,课程名、成绩)
SELECT
S.Sno,
S.Sname,
C.Cname,
SC.Degree
FROM
Student023 S
JOIN
Score023 SC ON S.Sno = SC.Sno
JOIN
Course023 C ON SC.Cno = C.Cno
WHERE
SC.Degree = (
SELECT MAX(Degree)
FROM Score023
WHERE Cno = SC.Cno
);
- 查询有成绩不及格的同学的学号,姓名。
SELECT DISTINCT
S.Sno,
S.Sname
FROM
Student023 S
JOIN
Score023 SC ON S.Sno = SC.Sno
WHERE
SC.Degree < 60;
- 查询选修两门及两门以上课程的学生学号及姓名,课程名,成绩,并保存到’SCBXXX’表中。
SELECT
S.Sno,
S.Sname,
C.Cname,
SC.Degree
INTO
SCB023
FROM
Student023 S
JOIN
Score023 SC ON S.Sno = SC.Sno
JOIN
Course023 C ON SC.Cno = C.Cno
WHERE
S.Sno IN (
SELECT Sno
FROM Score023
GROUP BY Sno
HAVING COUNT(*) >= 2
);
- 查询所有学生的操作系统成绩及排名(学号,姓名,成绩,排名)(不用排序函数)
SELECT
S.Sno,
S.Sname,
SC.Degree,
(SELECT COUNT(*) + 1
FROM Score023 SC2
JOIN Student023 S2 ON SC2.Sno = S2.Sno
JOIN Course023 C2 ON SC2.Cno = C2.Cno
WHERE C2.Cname = '操作系统' AND SC2.Degree > SC.Degree) AS Rank
FROM
Student023 S
JOIN
Score023 SC ON S.Sno = SC.Sno
JOIN
Course023 C ON SC.Cno = C.Cno
WHERE
C.Cname = '操作系统';
- 查询(没)有选修任何课程学生的信息(学号,姓名,等);
SELECT *
FROM Student023
WHERE Sno NOT IN (SELECT DISTINCT Sno FROM Score023);
- 查询所以成绩都及格的学生的信息(学号,姓名,课程号,课程名,成绩,最低成绩)(any ,some,all)
SELECT
S.Sno,
S.Sname,
C.Cno,
C.Cname,
SC.Degree,
(SELECT MIN(Degree) FROM Score023 WHERE Sno = S.Sno) AS MinScore
FROM
Student023 S
JOIN
Score023 SC ON S.Sno = SC.Sno
JOIN
Course023 C ON SC.Cno = C.Cno
WHERE
S.Sno NOT IN (
SELECT DISTINCT Sno
FROM Score023
WHERE Degree < 60
);
-
查询成绩有不及格的学生的信息(学号,姓名,课程号,课程名,成绩, 最低成绩)(any ,some,all)
SELECT
S.Sno,
S.Sname,
C.Cno,
C.Cname,
SC.Degree,
(SELECT MIN(Degree) FROM Score023 WHERE Sno = S.Sno) AS MinScore
FROM
Student023 S
JOIN
Score023 SC ON S.Sno = SC.Sno
JOIN
Course023 C ON SC.Cno = C.Cno
WHERE
S.Sno IN (
SELECT DISTINCT Sno
FROM Score023
WHERE Degree < 60
);
收获:
学会了使用子查询解决复杂问题
理解了窗口函数(OVER PARTITION BY)的应用场景
实现了数据排名功能(不使用排序函数)