1. 程式人生 > 其它 >sql巢狀查詢

sql巢狀查詢

巢狀查詢概述

一個 SELECT-FROM-WHERE 語句稱為一個查詢塊,將一個查詢塊巢狀在另一個查詢塊的 WHERE 子句 或 HAVING 短語的條件中的查詢稱為巢狀查詢

不相關子查詢

子查詢的查詢條件不依賴父查詢

相關子查詢

子查詢的查詢條件依賴父查詢

帶有IN謂詞的子查詢

查詢與“張三”在同一個系學習的學生

  1. 確定“張三”所在的系

    SELECT Sdept
    FROM student
    WHERE Sname='張三';
    

    結果為"CS"

  2. 查詢"CS"系的所有學生

    SELECT Sno, Sname, Sdept
    FROM student
    WHERE Sdept='CS';
    
  3. 將1的查詢巢狀進2的查詢中

    SELECT Sno, Sname, Sdept
    FROM student
    WHERE Sdept IN (
    	SELECT Sdept
    	FROM student
    	WHERE Sname='張三'
    );
    
  4. 用自身連線查詢實現

    /*查詢與“張三”在同一個系學習的學生學號和姓名*/
    SELECT second.Sno, second.Sname, second.`Sdept`
    FROM student FIRST, student SECOND
    WHERE first.`Sname`='張三' AND first.`Sdept`=second.`Sdept`;
    

查詢選修了課程名為“資訊系統”的學生學號和姓名

  1. 在Course表中找“資訊系統”課程的課程號

    SELECT Cno
    FROM course
    WHERE Cname='資訊系統';
    

    結果為3

  2. 在SC表中找選修了3號課程的學生的學號

    SELECT Sno 
    FROM sc
    WHERE Cno='3';
    

    結果為200215121和200215122

  3. 最後在Student表中取出學號和姓名

    SELECT Sno, Sname
    FROM student
    WHERE Sno='200215121' OR Sno='200215122';
    
  4. 將上面三個操作巢狀

    /*查詢選修了課程名為“資訊系統”的學生學號和姓名*/
    SELECT Sno, Sname
    FROM student
    WHERE Sno IN(
    	SELECT Sno
    	FROM sc
    	WHERE Cno IN(
    		SELECT Cno
    		FROM course
    		WHERE Cname='資訊系統'
    	)
    );
    
  5. 用連線查詢實現

    /*查詢選修了課程名為“資訊系統”的學生學號和姓名*/
    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`
);