內容來源於網上:https://blog.csdn.net/qq_27571221/article/details/53090467
將主查詢的數據,放到子查詢中做條件驗證,根據驗證結果(TRUE 或 FALSE)來決定主查詢的數據結果是否得以保留。
下面來三張表的實例
我們先介紹下使用的3個數據表:
student數據表:
sno 學號 | sname | ssex | sage |
---|---|---|---|
20161181 | Altair | 男 | 20 |
20161182 | Desmond | 男 | 18 |
20161183 | Ezio | 男 | 22 |
20161184 | Christina | 女 | 19 |
course數據表:
cno 課程編號 | cname 課程名 |
---|---|
1 | C語言 |
2 | 數據結構 |
3 | 信號與系統 |
4 | 模擬電子技術 |
5 | 高數 |
sc數據表:
sno 學號 | cno 課程編號 | grade 成績 |
---|---|---|
20161181 | 1 | 99 |
20161182 | 2 | 98 |
20161181 | 2 | 97 |
20161181 | 3 | 95 |
20161184 | 3 | 92 |
20161181 | 4 | 90 |
20161181 | 5 | 88 |
20161183 | 5 | 58 |
EXISTS
EXISTS代表存在量詞∃。帶有EXISTS謂詞的子查詢不返回任何數據,只產生邏輯真值“true”或者邏輯假值“false”。
一個例子1.1:
要求:查詢選修了課程”信號與系統“的同學
SELECT s.Sname FROM student s
WHERE EXISTS
(SELECT * FROM sc, course c WHERE sc.sno = s.sno AND sc.cno = c.cno AND c.cname = '信號與系統')
使用存在量詞EXISTS后,若內層查詢結果為非空,則外層的WHERE子句返回值為真,否則返回值為假。
在本例中,首先分析最內層的語句:
SELECT * FROM sc, course c WHERE sc.sno = s.sno AND sc.cno = c.cno AND c.cname = '信號與系統'
- 1
本例中的子查詢的查詢條件依賴於外層父查詢的某個屬性值(本例中的是Student的Sno值),這個相關子查詢的處理過程是:
首先取外層查詢中(student)表的第一個元組,根據它與內層查詢相關的屬性值(Sno值)處理內層查詢,若外層的WHERE返回為真,則取外層查詢中該元組的Sname放入結果表;
然后再取(student)表的下一組,重復這一過程,直至外層(Student)表全部檢查完畢。
查詢結果表:
Sname |
---|
Altair |
Christina |
NOT EXISTS
與EXISTS謂詞相對的是NOT EXISTS謂詞。使用存在量詞NOT EXISTS后,若對應查詢結果為空,則外層的WHERE子語句返回值為真值,否則返回假值。
例子2.1:
要求:查詢沒有選修課程”信號與系統“的同學
SELECT s.Sname FROM student s
WHERE NOT EXISTS
(SELECT * FROM sc, course c WHERE sc.sno = s.sno AND sc.cno = c.cno AND c.cname = '信號與系統')
使用NOT EXISTS之后,若內層查詢結果為非空,則對應的NOT EXISTS不成立,所以對應的WHERE語句也不成立。
在例子1.1中李勇同學對應的記錄符合內層的select語句的,所以返回該記錄數據,但是對應的NOT EXISTS不成立,WHERE語句也不成立,表示這不是我們要查詢的數據。
查詢結果表:
Sname |
---|
Desmond |
Ezio |
例子2.2(這是一個用NOT EXISTS表示全稱量詞的例子):
要求:查詢選修了全部課程的學生姓名。
SQL語句:
SELECT Sname
FROM Student
WHERE NOT EXISTS
(SELECT * FROM Course WHERE NOT EXISTS
(SELECT * FROM SC WHERE Sno=Student.Sno AND Cno=Course.Cno)
);
這個算是一個比較復雜的sql語句了,兩個EXISTS和三個WHERE。
這個sql語句可以分為3層,最外層語句,最內層語句,中間層語句。
我們很關心最外層語句,因為結果表中的數據都是最外層的查詢的表中的數據,我們更關心最內層的數據,因為最內層的數據包含了全部的判斷語句,決定了student表中的那一條記錄是我們查詢的記錄。
我們由內而外進行分析:
最外層的student表中的第一條記錄是Altair同學對應的記錄,然后中間層的course表的第一條記錄是數據庫對應的記錄,然后對該數據進行判斷(最內層的WHERE語句),結果返回真,則內層的NOT EXISTS為假,
然后繼續對course表中的下一條記錄進行判斷,返現NOT EXISTS的值也為假,直到遍歷完course表中的所有的數據,內層的NOT EXISTS的值一直都是假,所以中間層的WHERE語句的值也一直都是假。
對應student的Altair記錄,course表中的所有的記錄對應的中間層的返回值為假,所以最外層的NOT EXISTS對應的值為真,最外層的WHERE的值也為真,則Altair對應的記錄符合查詢條件,裝入結果表中。
然后繼續對student表中的下一條記錄進行判斷,直達student表中的所有數據都遍歷完畢。
下面是我自己對這段sql的解讀:
先取一條student記錄,進入中層,再取一條course的記錄,進入內層,此時student的記錄和course的記錄,作為內層判斷的條件,比如此時我取的第一條記錄是Altair,那么我里面的Sql就可以寫成
SELECT * FROM Course WHERE NOT EXISTS
(SELECT * FROM SC WHERE Sno = '20161181' AND Cno=Course.Cno) )
此處 sno 20161181即Altair的學號,這條sql的意思是選出沒有被Altair選擇的課程,如果不存在,則返回false,再跟最外層的NOT EXISTS關聯,負負得正。每一條循環的意思就是指,篩選出的每一個學生都不存在沒有被他選取的那門課,即選了所有課。
最終查詢結果:
Sname |
---|
Altair |