SELECT:【例3.49】~【例3.59】
REF:教材3.4“數據查詢”的部分例題
1. 在SQLserver上運行,觀察運行效果,並把代碼寫到作業中。
2. 寫出自己的理解/收穫/心得體會(部分比較複雜的例題,建議增加測試方法和測試數據,舉一反三)。
REF:建表&插入數據
作業原地址:作業
目錄
-
連接查詢
若一個查詢同時涉及兩個以上的表,則稱之爲鏈接查詢。
鏈接查詢是關係數據庫中最主要的查詢,包括等值連接查詢、自然連接查詢、非等值連接查詢、自身連接查詢、外連接查詢和複合連接查詢等。
1.等值與非等值連接查詢
連接查詢的WHERE子句用來連接兩個表的條件稱爲連接條件或連接謂詞。
[<表名1>.]<列名1> <比較運算符> [<表名2>.]<列名2>
其中比較運算符主要有=、>、<、>=、<=、!=等。
連接謂詞中的列名稱爲連接字段。各連接字段類型必須是可比的。
【例3.49】查詢每個學生及其選修課程的情況。
SELECT Student.*, SC.*
FROM Student, SC
WHERE Student.Sno = SC.Sno; /*將Student與SC中同一學生的元組連接起來*/
【例3.50】對例3.49用自然連接完成。
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno = SC.Sno;
【例3.51】查詢選修2號課程且成績在90分以上的所有學生的學號和姓名。
SELECT Student.Sno,Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND /*連接謂詞*/
SC.Cno='2' AND SC.Grade>90; /*其他限定條件*/
注:查詢順序爲先查詢SC.Con='2',再查詢SC.Grade>90。
2.自身鏈接
一個表與其自己進行連接,稱爲表的自身連接。
【例3.25】查詢每一門課的間接先修課(即先修課的先修課)。
注:將Course表與其自身連接。要爲Course表取兩個別名,FIRST,SECOND。
SELECT FIRST.Cno,SECOND.Cpno
FROM Course FIRST,Course SECOND
WHERE FIRST.Cpno = SECOND.Cno;
3.外連接
於2.4.2節提到過外連接、左外連接、右外連接
外連接:把懸浮元組也保存在結果關係中,而在其他屬性上填空值(NULL),那麼這種連接就叫做外連接。
左外連接:如果只保留左邊關係R中的懸浮元組,就叫做左外連接。
右外連接:如果值保留右邊關係S中的懸浮元組,就叫做右外連接。
【例3.53】
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student LEFT OUTER JOIN SC ON(Student.Sno=SC.Sno);
/*也可以使用USING來去掉結果中的重複值:FROM Student LEFT OUTER JOIN SC USING (Sno);*/
4.多表連接
多表連接:兩個以上的表進行連接。
【例3.54】查詢每個學生的學號、姓名、選修的課程名及成績
SELECT Student.Sno,Sname,Cname,Grade
FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno;
-
嵌套查詢
一個SELECT-FROME-WHERE語句稱爲一個查詢塊。
將一個查詢塊嵌套在另一個查詢塊的WHERE子句或HAVING短語的條件中的查詢稱爲:嵌套查詢。
例如:
SELECT Sname /*外層查詢或父查詢*/
FROM Student
WHERE Sno IN
(SELECT Sno /*內層查詢或子查詢*/
FROME SC
WHERE Cno='2');
注:可以用多個簡單查詢構成複雜的查詢。
1.帶有IN謂語的子查詢
【例3.55】查詢與“劉晨”在同一個系學習的學生。
步驟:先分佈來完成此查詢,然後再構造嵌套查詢。
/*確定“劉晨”所在系名*/
SELECT Sdept
FROM Student
WHERE Sname='劉晨'; /*結果爲CS*/
/*查找所有在CS系學習的學生。*/
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept='CS';
不相關子查詢:
子查詢的查詢條件不依賴於父查詢。
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname='劉晨');
自身連接:
SELECT S1.Sno,S1.Sname,S1.Sdept
FROM Student S1,Student S2
WHERE S1.Sdept=S2.Sdept AND S2.Sname='劉晨';
【例3.56】查詢選修了課程名爲“信息系統”的學生學號和姓名。
SELECT Sno,Sname /*最後在Student關係中取出Sno和Sname*/
FROM Student
WHERE Sno IN
(SELECT Sno /*然後在SC關係中找出選修了3號課程的學生學號*/
FROM SC
WHERE Cno IN
(SELECT Cno /*首先在Course關係中找出“信息系統”的課程號,爲3號*/
FROM Course
WHERE Cname='信息系統'
)
);
連接查詢:
SELECT Student.Sno,Sname
FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND
SC.Cno=Course.Cno AND
Course.Cname='信息系統';
注:如果子查詢的查詢條件依賴於父查詢,這類子查詢稱爲相關子查詢,整個查詢語句稱爲相關嵌套查詢語句。
3.帶有比較運算符的子查詢
指父查詢與子查詢之間用比較運算符進行連接。>、<、=、>=、<=、!=或<>等。
例如在【例3.55】中,由於一個學生只可能在一個系學習,也就是說內查詢的結果收到一個值,因此可以用=代替IN:
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept=(SELECT Sdept
FROM Student
WHERE Sname='劉晨');
【例3.57】找出每個學生超過他選修課程平均成績的課程號。
SELECT Sno,Cno
FROM SC x
WHERE Grade>=(SELECT AVG(Grade)
FROM SC y
WHERE y.Sno=x.Sno);
x:是表SC的別名,又稱爲元組變量,可以用來表示SC的一個元組。
步驟:
①從外層查詢中取出SC的一個元組x,將元組x的Sno值(201215121)傳送給內層查詢;
②執行內層查詢,得到值88(近似值),用該值代替內層查詢,得到外層查詢;
③執行這個查詢。
然後外層查詢取出下一個元組重複上述步驟,直到外層的SC元組全部處理完畢。
3.帶有ANY(SOME)或ALL謂語的子查詢
>ANY |
大於子查詢結果中的某個值 |
>ALL | 大於子查詢結果中的所有值 |
<ANY | 小於子查詢結果中的某個值 |
<ALL | 小於子查詢結果中的所有值 |
>=ANY | 大於等於子查詢結果中的某個值 |
>=ALL | 大於等於子查詢結果中的所有值 |
<=ANY | 小於等於子查詢結果中的某個值 |
<=ALL | 小於等於子查詢結果中的所有值 |
=ANY | 等於子查詢結果中的某個值 |
=ALL |
等於子查詢結果中的所有值 (通常沒有實際意義) |
!=(或<>)ANY | 不等於子查詢結果中的某個值 |
!=(或<>)ALL | 不等於子查詢結果中的任何一個值 |
【例3.58】查詢非計算機科學系中比計算機科學系任意一個學生年齡小的學生姓名和年齡。
SELECT Sname,Sage
FROM Student
WHERE Sage<ANY(SELECT Sage
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS'; /*注:這是父查詢塊中的條件*/
步驟:先處理子查詢,找出CS系中所有學生的年齡,構成一個集合(20,19);然後處理父查詢,找所有不是CS系且年齡小於20 或 19的學生。
聚集函數:
SELECT Sname,Sage
FROM Student
WHERE Sage <
(SELECT NAX(Sage)
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS';
步驟:首先用子查詢找出SC系中最大年齡(20),然後在父查詢中查所有非CS系且年齡小於20歲的學生。
【例3.59】查詢非計算機科學系中比計算機科學系所有學生年齡都小的學生姓名及年齡。
SELECT Sname,Sage
FROM Student
WHERE Sage < ALL
(SELECT Sage
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS';
聚集函數:
SELECT Sname,Sage
FROM Student
WHERE Sage <
(SELECT MIN(Sage)
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS';
總結:
這次作業基本都是查詢。照着例題做,目前沒遇到什麼錯誤或者問題。感覺這個好像和離散數學差不多,各種邏輯,比如查詢的順序步驟,代碼不一樣,查詢的方式也不一樣。
代碼差不多能看的懂了,跟做數學題套公式似的,敲多了也熟練了。不過這次費時間的還是敲代碼,一個一個敲還是累啊。
上期傳送陣:【數據庫】作業6——SQL練習3 - SELECT(單表查詢)
下期傳送陣:————
!!!備註!!!————忘記發截圖了(之後補上)
完成時間:2h19min
以上
————(2020.3.22)