SQL中exists的用法實戰記錄
首先注意拼寫(因為我老是記錯字母順序或者位數),exists,是6個字母;發音:英[ɪɡˈzɪsts],原型:exist;
舉例
下面直接進入正題,先上個例子
select * from user u where u.age<25 and EXISTS ( select * from grade g where g.g_name=u.name )
含義:查詢user表年齡小於25歲,並且在grade表不存在的使用者;通過g.g_name=u.name關聯;
以下幾個小圓點可以幫助理解上述SQL的查詢過程:
- 查詢user表第一條資料,age是小於25的,name=Jone,這時去grade表查g_name=Jone是否有資料,有資料,則返回user表第一條資料;
- 查詢user表第二條資料,age不滿足小於25,不查出user表第二條資料;
- 查詢user表第三條資料,age是小於25的,name=Jack,這時去grade表查g_name=Jack是否有資料,無資料,不查出user表第三條資料;
- ......
上述SQL用IN來實現,結果是一樣的:
select * from user u where u.age<25 and u.name in (select g_name from grade);
查詢過程:
- DBMS首先處理最裡面的子查詢。系統首先執行“select g_name from grade”語句,生成grade表中所有使用者的g_name集;
- 然後DBMS一次處理user表中的一行記錄,並且將每行記錄中的name列值與子查詢結果集中的SNO值進行比較;
- 如果子查詢中能找到正在處理的name值,where子句求值為True,DBMS則將該記錄的相關資訊歸入結果表。如果未找到,則DBMS轉而去處理user表中下一行而捨棄該行資料;
- ......
至於exists和in的區別,我現在是想到哪個用哪個,沒有專門研究過,網上文章很多,大家可以去搜索一下~
查閱資料後的總結
簡單的EXISTS查詢語句表示如下:
SELECT column_name FROM table_name WHERE [NOT] EXISTS (subquery)
只要子查詢subquery中能查詢出資料,EXISTS(subquery)返回True,則外層查詢的WHERE子句的結果也為True,則返回外層查詢的這條資料。否則,就不返回外層查詢的這條資料。
注意點:
1、需要注意EXISTS前可以加NOT,用於否定:
2、子查詢subquery中查詢的欄位不重要,怎麼寫都對,無論是SELECT * 還是SELECT column_name ,該子查詢返回的結果要麼是True,要麼是False(既不會返回*,也不會返回具體列值);
課後練習
1、在COURESE表中查詢在STUDENT表中未被選修的課程的課程號、課程名稱、學時和考試時間資訊;
SELECT CNO,CNAME,CTIME,CTEST FROM COURSE AS C WHERE NOT EXISTS(SELECT * FROM STUDENT WHERE CNO=C.CNO)
2、在Teacher表中查詢女教師開設的、7月份考試的課程號、開課教師的姓名以及教師所在的系;
分析:
(1)首先明確我們要查的是Tacher表的資料:CNO、TNAME、DNAME;
(2)但要查的不是Tacher表所有資料,是有條件的。
- 條件一:TEACHER.TSEX='女'
- 條件二:MONTH(COURSE.CTEST)=7
- TEACHER表和COURSE表如何關聯呢?TEACHER.CNO=COURSE.CNO
(3)想一想,在TEACHER表已經查出了女教師的資訊及所教的課程號,在COURSE表也查出了7月考試的課程號。如果TEACHER表女教師所教的課程號在COURSE表存在且其考試月份是在7月,那就是我們要查的資料啦,實際我們要查詢的是Teacher表中女老師開設的課程和Course表中7月考試的課程的交集。
SELECT CNO,TNAME,DNAME FROM TEACHER WHERE TSEX='女' ANX EXISTS(SELECT * FROM COURSE WHERE MONTH(CTEST)=7 AND CNO=TEACHER.CNO) ORDER BY CNO
最後,本人簡單粗暴的一句話總結(大家可以忽略):exists就是查詢A表中滿足條件並且在子查詢B表中存在的資料。
參考書籍:《SQL查詢的藝術》(張權,郭天嬌)