sql巢狀查詢
巢狀查詢概述
一個 SELECT-FROM-WHERE 語句稱為一個查詢塊,將一個查詢塊巢狀在另一個查詢塊的 WHERE 子句 或 HAVING 短語的條件中的查詢稱為巢狀查詢
不相關子查詢
子查詢的查詢條件不依賴父查詢
相關子查詢
子查詢的查詢條件依賴父查詢
帶有IN
謂詞的子查詢
查詢與“張三”在同一個系學習的學生
-
確定“張三”所在的系
SELECT Sdept FROM student WHERE Sname='張三';
結果為"CS"
-
查詢"CS"系的所有學生
SELECT Sno, Sname, Sdept FROM student WHERE Sdept='CS';
-
將1的查詢巢狀進2的查詢中
SELECT Sno, Sname, Sdept FROM student WHERE Sdept IN ( SELECT Sdept FROM student WHERE Sname='張三' );
-
用自身連線查詢實現
/*查詢與“張三”在同一個系學習的學生學號和姓名*/ SELECT second.Sno, second.Sname, second.`Sdept` FROM student FIRST, student SECOND WHERE first.`Sname`='張三' AND first.`Sdept`=second.`Sdept`;
查詢選修了課程名為“資訊系統”的學生學號和姓名
-
在Course表中找“資訊系統”課程的課程號
SELECT Cno FROM course WHERE Cname='資訊系統';
結果為3
-
在SC表中找選修了3號課程的學生的學號
SELECT Sno FROM sc WHERE Cno='3';
結果為200215121和200215122
-
最後在Student表中取出學號和姓名
SELECT Sno, Sname FROM student WHERE Sno='200215121' OR Sno='200215122';
-
將上面三個操作巢狀
/*查詢選修了課程名為“資訊系統”的學生學號和姓名*/ SELECT Sno, Sname FROM student WHERE Sno IN( SELECT Sno FROM sc WHERE Cno IN( SELECT Cno FROM course WHERE Cname='資訊系統' ) );
-
用連線查詢實現
/*查詢選修了課程名為“資訊系統”的學生學號和姓名*/ SELECT student.`Sno`, student.`Sname` FROM student, sc, course WHERE Cname='資訊系統' AND course.`Cno`=sc.`Cno` AND sc.`Sno`=student.`Sno`;
帶有比較運算的子查詢
- 當能確切知道內層查詢返回單值時,可用比較運 算符( > , < , = , >= , <= , != 或 < > )
- 與 ANY 或 ALL 謂詞配合使用
假設一個學生只可能在一個系學習,並且必須屬於一個系,可以用 = 代替 IN
查詢與“張三”在同一個系學習的學生
用 = 替代謂詞 IN
/*查詢與“張三”在同一個系學習的學生學號和姓名*/
SELECT Sno, Sname, Sdept
FROM student
WHERE Sdept = (
SELECT Sdept
FROM student
WHERE Sname='張三'
);
找出每個學生超過他選修課程平均成績的課程號
SELECT Sno, Cno
FROM sc X
WHERE Grade > (
SELECT AVG(Grade)
FROM sc Y
WHERE y.`Sno`=x.`Sno`
);
此例為相關子查詢,外層查詢取出sc的一個元組x,將x.Sno(如:200215121)傳遞給內層查詢,內層查詢相當於
SELECT AVG(Grade)
FROM sc
WHERE y.`Sno`='200215121';
因此內層查詢計算得學號為200215121學生得平均成績,並將其返回給外層查詢(假定為88),則外層查詢相當於
SELECT Sno, Cno
FROM sc X
WHERE Grade > 88;
帶有ANY或ALL謂詞的子查詢
ANY:任意一個值
ALL:所有值
查詢其他系中比電腦科學某一學生年齡小的學生姓名和年齡
關鍵詞:某一
SELECT Sname, Sage
FROM student
WHERE Sdept!='CS' AND Sage<ANY(
SELECT Sage
FROM student
WHERE Sdept='CS'
);
先處理子查詢,CS系所有學生的年齡構成一個集合,再處理父查詢,找出所有不是CS系且年齡小於20或19的學生,相當於使用聚集函式MAX
SELECT Sname, Sage
FROM student
WHERE Sdept!='CS' AND Sage<(
SELECT MAX(Sage)
FROM student
WHERE Sdept='CS'
);
查詢其他系中比計算機科學系所有學生年齡都小的學生姓名及年齡
關鍵詞:所有
SELECT Sname, Sage
FROM student
WHERE Sdept!='CS' AND Sage<ALL(
SELECT Sage
FROM student
WHERE Sdept='CS'
);
相當於使用聚集函式MIN
SELECT Sname, Sage
FROM student
WHERE Sdept!='CS' AND Sage<(
SELECT MIN(Sage)
FROM student
WHERE Sdept='CS'
);
帶有EXISTS謂詞的子查詢
帶有 EXISTS 謂詞的子查詢不返回任何資料,只產生邏輯真 值“ true” 或邏輯假值“ false”
-
若內層查詢結果非空,則外層的 WHERE 子句返回真值
-
若內層查詢結果為空,則外層的 WHERE 子句返回假值
查詢所有選修了 1 號課程的學生姓名
SELECT Sname
FROM student
WHERE EXISTS (
SELECT *
FROM sc
WHERE sc.`Cno`='1' AND sc.`Sno`=student.`Sno`
);
依次取出student中每個元組的Sno值,用此值去檢查sc關係,若sc中存在這樣的元組,其Sno為外層查詢的Sno,且Cno為1,則取Sname送入結果集
用連線查詢實現
/*查詢所有選修了 1 號課程的學生姓名*/
SELECT Sname
FROM student, sc
WHERE sc.`Cno`='1' AND student.`Sno`=sc.`Sno`;
查詢沒有選修 1 號課程的學生姓名
SELECT Sname
FROM student
WHERE NOT EXISTS (
SELECT *
FROM sc
WHERE sc.`Cno`='1' AND sc.`Sno`=student.`Sno`
);