?夕陽無限好? ? ? ? ? ?
? ? ? ? ? ? 只是近黃昏
一、子查詢
? ? ? ? 1.1 定義
????????將一個查詢語句嵌套到另一個查詢語句內部的查詢
? ? ? ? 我們通過具體示例來進行演示,這一篇博客更側重于通過具體的小問題來引導大家獨立思考,然后熟悉子查詢相關的知識點
? ? ? ? 1.2 問題1
????????誰的工資比Tom高
方式1:
SELECT name,salary
FROM employees
WHERE name='Tom'SELECT NAME,salary
FROM employees
WHERE salary > 500方式2:自連接
SELECT t2.NAME,t2.salary
from employees t1,employees t2
WHERE t2.salary > t1.salary AND
t1.name = 'Tom'方式3:子查詢
# 外部
SELECT name,salary
FROM employees
WHERE salary > (
# 內部SELECT salary FROM employeesWHERE name ='Tom'
)
? ? ? ? 1.3 稱謂的規范
? ? ? ? (1) 外查詢(主查詢)、內查詢(子查詢)?
? ? ? ? (2) 子查詢(內查詢)在主查詢之前一次執行完成
? ? ? ? (3) 子查詢的結果被主查詢(外查詢)使用
? ? ? ? 1.4 注意事項
? ? ? ? (1) 子查詢要包含在括號內
????????(2) 將子查詢放在比較條件的右側,提高可讀性
? ? ? ? (3) 單行操作符對應單行子查詢,多行操作符對應多行子查詢
? ? ? ? 1.5 子查詢分類
????????1.單行子查詢和多行子查詢
????????子查詢部分只返回一個值供使用,就比如C語言中副函數每次return只返回一個值,這種情況叫做單行子查詢
????????2.根據內查詢是否被執行多次
????????分為相關子查詢和不相關子查詢
????????不相關子查詢:子查詢固定返回的值不受外部的影響
二、單行子查詢
? ? ? ? 2.1 單行操作符: = > < >= <=> !=
? ? ? ? 2.2 練習1:查詢工資大于id為3的員工工資的員工信息
SELECT id,name,salary
from employees
WHERE salary > (SELECT salaryFROM employeesWHERE id=3
)
? ? ? ? 2.3 練習2:返回top_id與id=3相同的員工的工資比他多的 name、id
SELECT name,id,salary
FROM employees
WHERE top_id = (SELECT top_idFROM employeesWHERE id = 3
)
AND salary > (SELECT salaryFROM employeesWHERE id =3
)
? ? ? ? 2.4 練習3:返回公司里面工資最少的人的信息,包含name、id、top_id、salary
SELECT name,id,top_id,salary
FROM employees
WHERE salary = (SELECT MIN(salary)FROM employees
)
? ? ? ? 2.5 問題4:查詢最低工資大于top_id為1的部門的最低工資的部門top_id和最低工資
SELECT top_id,MIN(salary)
FROM employees
GROUP BY top_id
HAVING MIN(salary) > (SELECT MIN(salary)FROM employeesWHERE top_id = 1
)
三、多行子查詢
? ? ? ? 3.1 引言
? ? ? ? 與單行查詢不同的是,內查詢返回多行,也就是多個值,你用一個可以選擇其中的一個作為你的選擇,你也可以全部都接收,但需要用同等數量的字段來接受
? ? ? ? 3.2 命令語句
? ? ? ? (1) IN 等于列表中的任意一個
? ? ? ? (2) ANY 只選一個
? ? ? ? (3) SOME ANY的別名和ANY作用一樣
? ? ? ? (4) ALL 全部選擇
? ? ? ? 3.3 練習: 這里演示一個 IN
# 查找工資等于各個top_id中最低工資的人員姓名
SELECT name,salary
FROM employees
WHERE salary IN (SELECT MIN(salary)FROM employeesGROUP BY top_id
)
? ? ? ? 3.4?練習: 這里演示ALL
按照top_id進行分組,求平均工資最小的那一組
SELECT top_id,AVG(salary)
FROM employees
GROUP BY top_id
HAVING avg(salary)<=ALL(# 小于所有部門的最小值就相當于值最小的那個組SELECT AVG(salary)FROM employeesGROUP BY top_id
)
????????3.5 注意
? ? ? ? 這里我們要特別注意下空值問題,下面的題目中,我們的department_id中包含一個空值,當我們對其內查詢時,就會出現錯誤,此時我們可以通過加注判斷條件來避免
? ? ? ? 報錯演示
# 查詢已經分配好部門的員工信息
# 示例
SELECT name,department_id
FROM employees
WHERE department_id NOT IN (SELECT department_idFROM employees
)
四、相關子查詢
? ? ? ? 4.1 引入
? ? ? ? 在這里,我們采用具體練習的方法來帶領大家一步一步的深入了解什么是相關子查詢
? ? ? ? 4.2 練習1:查詢員工中工資大于本部門平均工資的員工的name,salary
? ? ? ? 我們先從查詢員工中工資大于本公司平均工資的員工的name,salary 開始,方便大家進行對比發現
# 查詢員工中工資大于本公司平均工資的員工的name,salary
SELECT name,salary
FROM employees
WHERE salary > (SELECT AVG(salary)FROM employees
)
?
? ? ? ? 然后我們用兩步逐步去對比發現相關子查詢特點
# 方式1:
SELECT name,salary,top_id
FROM employees t1
WHERE salary > (SELECT AVG(salary)FROM employees t2WHERE top_id = t1.top_id
)
? ? ? ? 這里是利用查詢過程中,是一條一條進行的特點,通過自連接的方式,建立類似于for循環的方式,動態更新AVG(salary),實現分部門、逐員工檢查
# 方式2
SELECT e.name,e.salary
FROM employees e,(# 在此中的查詢以一張表對的形式返回,定義別名為 t,同時后面比較時需要用AVG(salary),但是出了這個括號,AVG(salary)就將作為一個列名出現,但是不能被原樣調用,所以取一個別名 avg。SELECT top_id,AVG(salary) avgFROM employeesGROUP BY top_id) t
WHERE e.top_id = t.top_id
AND e.salary > t.avg
? ? ? ? 4.3 練習2
# 查詢員工的id,salary,按照departments中的manger_id進行排序
SELECT id,salary
FROM employees
ORDER BY (SELECT mange_idFROM departmentsWHERE employees.department_id=departments.department_id
)
? ? ? ? 在上面命令基礎上,展示更多的信息
SELECT id,salary,name,(SELECT nameFROM departmentsWHERE employees.department_id=departments.department_id
) 'names',(SELECT mange_idFROM departmentsWHERE employees.department_id=departments.department_id
) 'mange_id'
FROM employees
ORDER BY (SELECT mange_idFROM departmentsWHERE employees.department_id=departments.department_id
)
? ? ? ? 4.4 小結論
????????在 SELECT中,除了 LIMIT 和 GROUP BY中,其他位置都可以聲明子查詢
? ? ? ? 4.5?EXISTS / NOT EXISTS
# 查詢公司所有管理者的信息
SELECT DISTINCT t1.name, t1.top_id, t1.id
FROM employees t1,employees t2
WHERE t1.id = t2.top_id
? ? ? ? (1) EXISTS首先執行外層查詢,再執行內層查詢?
? ? ? ? (2) 取出外層表中的第一行數據,代入子查詢中執行
? ? ? ? (3) 如果子查詢返回結果,則保留該行(對于EXISTS)或排除該行(對于NOT EXISTS)
? ? ? ? (4) 接著處理外層表中的下一行,重復上述過程?
五、結語
????????山不在高,有仙則名;水不在深,有龍則靈。希望我們都可以通過自己的努力成為那個關鍵的要素
須知少日拏云志,曾許人間第一流。我們還年輕,我們還有無限可能!