一、實驗名稱和性質
子查詢
驗證 設計
二、實驗目的
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)的應用場景
實現了數據排名功能(不使用排序函數)