9.4 數據的嵌套查詢
所謂嵌套查詢,就是在一個查詢語句中,嵌套進另一個查詢語句,即,查詢語句中可以使用另一個查詢語句中得到的查詢結果,子查詢可以基于一張表或者多張表。子查詢中常用的操作符有ANY、SOME、ALL、IN、EXISTS等。
9.4.1 使用比較運算符的子查詢
子查詢中可以使用的比較運算符有“<”“<=”“=”“>=”和“!=”等。
為演示子查詢操作,下面創建員工部門信息(dept表),具體的表結構如下表:
dept表結構
字段名 | 字段說明 | 數據類型 | 主鍵 | 外鍵 | 非空 | 唯一 |
deptID | 部門編號 | int | 是 | 是 | 是 | 是 |
deptName | 部門名稱 | varchar(50) | 否 | 否 | 是 | 否 |
addr | 部門地址 | varchar(100) | 否 | 否 | 否 | 否 |
在數據庫mydatabase中,創建部門信息表:
CREATE TABLE dept
(deptID INT PRIMARY KEY,deptName VARCHAR(50),addr VARCHAR(100)
)
創建好后,向表中錄入數據,如下表:
deptID | deptName | addr |
1 | 行政部 | 行政樓101室 |
2 | 人事部 | 行政樓102室 |
3 | 銷售部 | 行政樓103室 |
4 | 財務部 | 行政樓104室 |
向數據表中添加數據記錄,具體SQL語句如下:
INSERT INTO dept
VALUES (1,'行政部','行政樓101室'),(2,'人事部','行政樓102室'),(3,'銷售部','行政樓103室'),(4,'財務部','行政樓104室')
例:在dept表中查詢工作地點addr等于“行政樓101室”的部門編碼deptID,然后在員工信息表employee中查詢所有該部門編碼的員工信息
SELECT * FROM employee WHERE deptcode=
(SELECT deptID FROM dept WHERE addr='行政樓101室')
例:在dept表中查詢addr等于“行政樓101室”的部門編號deptID,然后在employee中查詢所有非該部門的員工信息
SELECT * FROM employee WHERE deptcode !=
(SELECT deptID FROM dept WHERE addr='行政樓101室')
9.4.2 使用IN的子查詢
IN關鍵字主要用來判斷某個列是否在某個范圍內,在子查詢中,通常用在查詢結果的前面,用于判斷查詢結果中是否有符合條件的數據,語法如下:
SELECT col_name1,col_name2,...
FROM table_name1
WHERE col_name
IN (SELECT col_nameX FROM table_name2 WHERE conditions)
💡提示:
關鍵字IN后面是一個子查詢,并且這個子查詢只能返回一列值,另外,這個返回值的數據類型必須與IN前面列的數據類型一致。
例:在employee中,查詢員工編號為“101”的員工所在的部門編碼,再根據該編碼,查詢其部門名稱:
SELECT deptName FROM dept
WHERE deptId IN
(SELECT deptcode FROM employee WHERE code='101')
這個例子說明,SQL在處理SELECT語句的時候,實際上執行了兩個操作過程,即先執行內層子查詢,再執行外層查詢,內層的結果作為外層的條件使用。
SELECT語句中可以使用NOT IN運算符,其作為與IN 正好相反。
例:與前一個例子類似,但是在SELECT語句中使用NOT IN運算符
9.4.3 使用ANY的子查詢
ANY關鍵字也是在子查詢中經常使用,它可以用于比較某一列的值是否全部都大于ANY后面的子查詢中查詢結果的最小值,或者小于ANY后面子查詢結果的最大值。
語法如下:
SELECT col_name1,col_name2,...
FROM table_name1
WHERE col_name operator ANY
(SELECT col_nameX FROM table_name2 WHERE conditions)
各參數說明:
- operator:就是比較運算符的統稱,實際代碼中可以是“<”“<=”“=”“>=”和“!=”等。
例:查詢人事部員工工資大于銷售部員工工資的員工信息
SELECT * FROM employee
WHERE salary > ANY
(SELECT salary FROM employee
WHERE deptcode = (SELECT deptid FROM dept WHERE deptName = '銷售部') )
AND deptcode=2
9.4.4 使用SOME的子查詢
SOME關鍵字的用法與ANY關鍵字用法類似,但是意義不同。
SOME通常用于比較滿足查詢結果中的任意值,而ANY要滿足所有值才可以。
語法如下:
SELECT col_name1,col_name2,...
FROM table_name1
WHERE col_name operator SOME
(SELECT col_nameX FROM table_name2 WHERE conditions)
例:查詢行政部和人事部所有員工的信息
SELECT * FROM employee
WHERE deptname = SOME ('人事部' or '行政部')
很顯然,在表employee里,沒有字段[deptname],這個字段位于表“dept”中,所以需要使用子查詢,先從“dept”中找到對應'人事部'和'行政部'的部門編碼,再通過部門編碼去表“employee”中取數。
上面的代碼修改為:
SELECT * FROM employee
WHERE deptcode = SOME
(SELECT deptid FROM dept WHERE deptname = '人事部' OR deptname = '行政部')
💡提示:
從結果可以發現,與IN關鍵字有完全相同的功能。
也就是說,在使用=SOME時,可以用IN替換
9.4.5 使用EXISTS的子查詢
EXISTS關鍵字代表“存在”,它應用于子查詢中,只要子查詢返回的結果為空,那么返回就是TRUE,此時外層查詢語句將被執行;否則就是FALSE,外層語句不執行。
通常情況下,EXSITS關鍵字用在WHERE子句中。
SELECT col_name1,col_name2,...
FROM table_name1
WHERE EXISTS (SELECT col_nameX FROM table_name2 WHERE conditions)
這里,當EXISTS后面的查詢語句有結果時,那么EXISTS前面的查詢就被執行,否則,不輸出任何數據。
例:如果表dept中存在deptid=1的部門,就把表employee所有的員工信息全部查詢出來
SELECT * FROM employee
WHERE EXISTS (SELECT 1 FROM dept WHERE deptid=1)
EXISTS關鍵字可以和條件表達式一起使用。
例:如果表dept中存在deptid=1的部門,就把表employee中salary大于3000元的記錄查詢出來
SELECT * FROM employee
WHERE salary > 3000
AND EXISTS (SELECT 1 FROM dept WHERE deptid=1)
NOT EXISTS與EXISTS使用方法相同,返回的結果相反。
例:如果表dept中不存在deptid=1的部門,就查詢表employee中的所有記錄
SELECT * FROM employee
WHERE NOT EXISTS (SELECT 1 FROM dept WHERE deptid=1)
因為表dept中存在,所以不查詢,返回結果為空。
📢注意:
EXISTS和NOT EXISTS的結果只取決于是否會返回行,而不取決于這些行的內容,所以這個子查詢輸入列表通常是無關緊要的。