一、概念描述
在SQL語言中,一個 SELECT-FROM-WHERE 語句稱為一個查詢塊。將一個查詢塊嵌套在另一個查詢塊的 WHERE 子句或 HAVING 短語的條件中的查詢稱為 嵌套查詢。例如:
SELECT Sname /*外層查詢或父查詢*/ FROM Student WHERE Sno IN (SELECT Sno /*內層查詢或子查詢*/ FROM SC WHERE Cno='2');
SQL語言允許多層嵌套查詢,即一個子查詢中還可以嵌套其他子查詢。
注意:子查詢的SELECT語句中不能使用 ORDER BY 子句,因為 ORDER BY 子句只能對最終查詢結果排序。
二、帶有IN謂詞的子查詢
在嵌套查詢中,子查詢的結果往往是一個集合,所以謂詞 IN 是嵌套查詢中最經常使用的謂詞。
查詢與“劉晨”在同一個系學習的學生
SELECT Sno,Sname,Sdept FROM Student WHERE Sdept IN (SELECT Sdept FROM Student WHERE Sname='劉晨');
查詢選修了課程名為“信息系統”的學生學號和姓名
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='信息系統';
三、帶有比較運算符的子查詢
帶有比較運算符的子查詢是指父查詢與子查詢之間用比較運算符進行連接。當用戶能確切知道內層查詢返回的是單個值時,可以用 >、<、=、>=、<=、!=、或<>等比較運算符。
找出每個學生超過他自己選修課程平均成績的課程號
SELECT Sno,Cno FROM SC X WHERE Grade >=(SELECT AVG(Grade) FROM SC y WHERE y.Sno=x.Sno);
四、帶有ANY(SOME)或ALL謂詞的子查詢
子查詢返回單值時可以用比較運算符,但返回多值時要用ANY(有的系統用SOME)或ALL謂詞修飾符。而使用ANY或ALL謂詞時則必須同時使用比較運算符。其語義如下:
>ANY |
大於子查詢結果中的某個值 |
>ALL |
大於子查詢結果中的所有值 |
<ANY |
小於子查詢結果中的某個值 |
<ALL |
小於子查詢結果中的所有值 |
>=ANY |
大於等於子查詢結果中的某個值 |
>=ALL |
大於等於子查詢結果中的所有值 |
<=ALL |
小於等於子查詢結果中的所有值 |
<=ANY |
大於等於子查詢結果中的某個值 |
=ANY |
等於子查詢結果中的某個值 |
=ALL |
等於子查詢結果中的所有值(通常沒有實際意義) |
!=(或<>)ANY |
不等於子查詢結果中的某個值 |
!=(或<>)ALL |
不等於子查詢結果中的任何一個值 |
查詢非計算機科學系中比計算機科學系任意一個學生年齡小的學生姓名和年齡
SELECT Sname,Sage FROM Student WHERE Sage<ANY (SELECT Sage FROM Student WHERE Sdept='CS') AND Sdept <> 'CS';
查詢非計算機科學系中比計算機科學系所有學生年齡都小的學生姓名和年齡
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';
在此把ANY、ALL與聚集函數的對應關系表示如下
五、帶有 EXISTS 謂詞的子查詢
帶有EXISTS 謂詞的子查詢不返回任何數據,只產生邏輯真值“true”或邏輯假值“false”。
查詢所有選修了1號課程的學生姓名
SELECT Sname FROM Student WHERE EXISTS (SELECT * FROM SC WHERE Sno=Student.Sno AND Cno='1');
使用存在量詞EXISTS后,若內層查詢結果為空,則外層的WHERE子句返回真值,否則返回假值。
查詢沒有選修1號課程的學生姓名
SELECT Sname FROM Student WHERE NOT EXISTS (SELECT * FROM SC WHERE Sno=Student.Sno AND Cno='1');
查詢選修了全部課程的學生姓名
由於沒有全稱量詞,可將題目的意思轉換成等價的用存在量詞的形式:查詢這樣的學生,沒有一門課程是他不選修的。
SELECT Sname FROM Student WHERE NOT EXISTS (SELECT * FROM Course WHERE NOT EXISTS (SELECT * FROM SC WHERE Sno=Student.Sno AND Cno=Course.Cno));
查詢至少選修了學生201215122選修的全部課程的學生號碼
SELECT DISTINCT Sno FROM SC SCX WHERE NOT EXISTS (SELECT * FROM SC SCY WHERE SCY.Sno='201215122' AND NOT EXISTS (SELECT * FROM SC SCZ WHERE SCZ.Sno=SCX.Sno AND SCZ.Cno=SCY.Cno));
六、總結
此次學習和整理了有關SQL與嵌套查詢相關的程序
- 帶有IN謂詞
- 帶有比較運算符
- 帶有ANY或ALL
- 帶有EXISTS謂詞
尤其應格外重視 ANY、ALL與聚集函數的對應關系,還有帶EXISTS時邏輯上的判斷。