數據庫 EXISTS與NOT EXISTS


EXISTS與NOT EXISTS

  • EXISTS:表示存在xxx。在查詢的外層添加一個EXISTS,當內層查詢有結果,則該EXISTS返回true,反之返回false
  • NOT EXISTS:表示不存在xxx。在查詢的外層添加一個NOT EXISTS,當內層查詢有結果,則該NOT EXISTS返回false,反之返回true
##表生成的過程 ``` SELECT Sname FROM Student WHERE NOT EXISTS(1) (SELECT * FROM Course WHERE NOT EXISTS(2) (SELECT * FROM SC WHERE Sno= Student.Sno AND Cno= Course.Cno)); ``` ###學生表 ![](http://images2015.cnblogs.com/blog/1017814/201704/1017814-20170422154233899-361931250.png) ###課程表 ![](http://images2015.cnblogs.com/blog/1017814/201704/1017814-20170422154308962-74150998.png) ###學生選課表 ![](http://images2015.cnblogs.com/blog/1017814/201704/1017814-20170422154327915-791639455.png)

以上面的為例:首先改例子中有兩個EXISTS,我們先從最里面的內容開始,當一個元組和課程表中的第一個元組在最里層循環中與SC.sno和SC.cno進行匹配的時候。

(情況1)若配上最內層的WHERE將該數據插入到臨時表中,第一個NOT EXISTS(指內層的NOT EXISTS,代碼中的(2))判斷該臨時表不為空則返回false。

(情況2)若沒有匹配上最內層的WHERE返回false,則不將數據插入到臨時的表中,第一個NOT EXISTS(是內層的NOT EXISTS,代碼中的(2))判斷結果表為空返回true


####當Course循環結束之后 ####第二個NOT EXISTS(最外層的NOT EXISTS,代碼上的(1))判斷該內層返回集是否為空。
####(1)若為內層的NOT EXISTS返回true,WHERE接收到true之后將數據插入臨時的結果集中,第二個NOT EXISTS判斷臨時表不為空,則返回false,不將內容添加到最終的結果集中。
####(2)若為內層的NOT EXISTS返回false,WHERE接收到false之后不將數據插入到臨時的結果集中,第二個NOT EXISTS判斷臨時表為空,則返回true,將內容添加到最終的結果集中。
####本人的語言表達能力不足,要是上面的內容沒有看明白的話,一下是我總結的方法:
#### WHERE語句是當判斷的結果為true的時候,將內容添加到結果集中,若為false的話,則不講內容添加到結果集中。
#### EXISTS是當查詢的表為非空的時候則返回true,當查詢的表為空的時候返回false。 #### NOT EXISTS則是當查詢的表為空的時候返回true,當查詢的表為非空的時候返回false。
``` //查詢選擇了全部課程的學生的查詢語句 SELECT Sno FROM Student s WHERE NOT EXIXTS( SELECT * FROM Course c WHERE NOT EXISTS( SELECT * FROM SC sc WHERE sc.sno = s.sno AND sc.cno = c.cno
        // 該查詢內部,每次查詢從學生表(sno)和課程表(cno)中獲取一條數據
        // 與學生選課表中的所有數據逐條比較,將符合條件的數據列出來
        //假如查詢結果有數據,Not Exists則返回false,Course表中則不添加該課程數據
        //假如查詢結果沒有數據,Not Exists則返回true,Couse表中則添加添加該課程數據
        //在Exists或Not Exists進行嵌套使用,相當於for循環進行嵌套使用。
    )
);
個人的理解:其中外層的Student與次外層的Course的組合分別與SC中的內容進程比較,將符合要求的內容進行保留
可以通過以下步驟的思路來實現:

STEP1:先取 Student 表中的第一個元組,得到其 Sno 列的值。
STEP2:再取 Course 表中的第一個元組,得到其 Cno 列的值。
STEP3:根據 Sno 與 Cno 的值,遍歷 SC 表中的所有記錄(也就是選課記錄)。若對於某個 Sno 和 Cno 的值來說,在 SC 表中找不到相應的記錄,則說明該 Sno 對應的學生沒有選修該 Cno 對應的課程。
STEP4:對於某個學生來說,若在遍歷 Course 表中所有記錄(也就是所有課程)后,仍找不到任何一門他/她沒有選修的課程,就說明此學生選修了全部的課程。
STEP5:將此學生放入結果元組集合中。
STEP6:回到 STEP1,取 Student 中的下一個元組。
STEP7:將所有結果元組集合顯示。


###<font color="red">若沒有聽明白的話可以通過上面的方法進行推到來得出自己的觀點</font>

##<font color="red">補充的內容</font>
####上述就涉及到SQL的不相關子查詢與相關子查詢
select Sno
From SC
Where Cno in (
    select Cno
    From Course
    Where Cname = '數據結構'
)
###首先通過子查詢得到課名為“數據結構”的課程的課號,然后遍歷SC(選課)表中的每一條選課記錄,若當前這條記錄的課號為"數據結構"這門課的課號,則將這條記錄的Sno列的值放到結果集里面去,最終我們可以得到所有選修了“數據結構”這門課的學生的學號。

###這種類型的的查詢是先執行子查詢,得到一個集合(或值),然后將這個集合(或值)作為一個常量帶入到父查詢的Where子句中去。如果單純地執行子查詢,也可以成功的。這種類型的查詢,叫做“不相關子查詢”
#查詢每個學生查過他選修的所有課程的平均成績的課程的課程號
SELECT AVG(Grade)
From sc
WHERE Sno = ?
###Sno = ?的位置應該是不斷地將Student表中的每一條記錄中的Sno列的值代入此處,然后求出該Sno對應的平均成績。我們需要的是輸入一些列的值,然后得到一系列對應的輸出。這個時候,我們就要用到另一種嵌套查詢,叫做“相關子查詢”。相關子查詢的意思就是<font color="red">子查詢中需要用到父查詢中的值</font>。

###判斷是否是“相關子查詢”,只要子查詢不能脫離父查詢單獨執行,那么就是“相關子查詢”。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM