MySQL 基础 ———— 子查询
引言
承接《MySQL 基礎 ———— 連接查詢》,本文介紹和展示SQL中子查詢的使用。
子查詢是出現在其他語句中的select 語句,也稱為內查詢。外部的查詢語句,稱為主查詢或外查詢。
一、子查詢的分類和支持的子句
按照子查詢出現的位置,可以分為:
select 后面、from 后面、where 或 having 后面、exists 后面(相關子查詢)。
按照子查詢的結果集或者功能,可以分為:
1、標量子查詢(單行子查詢,結果集只有一行一列)
2、列子查詢(多行子查詢,結果集是一列多行)
3、行子查詢(多列子查詢,結果集是一行多列)
4、表子查詢(結果集可能是多行多列)
各子句能夠支持的子查詢類型:?
SELECT 后面只支持標量子查詢。
FROM 后面支持表子查詢。
WHERE 或 HAVING 后面支持(重點):標量子查詢、列子查詢、行子查詢(較少)。
EXISTS 后面支持表子查詢。
二、子查詢的特點
1、子查詢都要放在小括號里
2、子查詢一般放在條件的右側
3、標量子查詢一般配合單行操作符使用:>? <? >=? <=? <>? 等,列子查詢一般配合多行操作符使用:IN ANY/SOME ALL 等。
三、標量子查詢(單行子查詢)
標量子查詢的結果集是單行單列,即一個確定的值。
員工表:
案例一:查詢工資大于王強工資的員工信息。思路:第一步,先查詢王強的工資,第二步,通過 where子句,進行篩選。
SELECT * FROM emp WHERE salary >= (SELECT salary FROM emp WHERE emp_name = '王強' );案例二:查詢部門與張建國的部門相同,工資大于孫巖工資的員工信息。
SELECT * FROM emp WHERE dept_id = (SELECT dept_id FROM emp WHERE emp_name = '張建國' ) AND salary > (SELECT salary FROM emp WHERE emp_name = '孫巖' );案例三:查詢部門最低工資大于 1 號部門最低工資的部門id 和 最低工資。
思路:第一步,先查詢 1 號部門的最低工資,第二步,根據上一步的結果集進行條件篩選。
SELECT dept_id, MIN(salary) 部門最低工資 FROM emp GROUP BY dept_id HAVING MIN(salary) > (SELECT MIN(salary)FROM empWHERE dept_id = 1 );四、列子查詢(多行子查詢)
列子查詢返回一列多行,結果集可以看做是某個字段的值的集合,比如 dept_id = {1, 2, 5}。可以配合 IN 、NOT IN 等多行比較操作符一起使用。
常見的多行比較操作符有:
| 操作符 | 含義 |
| IN / NOT IN | 等于或不等于結果集中的任意一個 |
| ANY / SOME | 和子查詢返回的某一個值比較 |
| ALL | 和子查詢返回的所有值比較 |
其中,IN 和 NOT IN 使用頻率非常高,ANY 和 SOME 含義相同,但是可讀性較差,含義容易混淆,而且可以使用其他方式代替,因此不常使用。例如:a > ANY(10, 20, 30) ,可以替換為:a > MIN(10, 20, 30)。
員工表:
案例一:查詢孫姓員工所在部門的全部員工信息。
SELECT * FROM emp WHERE dept_id IN(SELECT dept_id FROM emp WHERE emp_name LIKE '孫%' );五、行子查詢(一行多列)
行子查詢一定會查詢出多個列值,這就要求語法有一定的變化,有點類似多個篩選條件,比如:
案例一:查詢員工編號最小,且工資最高的員工:
SELECT * FROM emp WHERE (emp_id, salary) = (SELECT MIN(emp_id), MAX(salary) FROM emp )案例二:查詢部門id > 2, 且工資 > 8000 的員工信息:
SELECT * FROM emp WHERE (dept_id, salary) = (SELECT dept_id, salary FROM empWHERE dept_id > 2AND salary > 8000 )行子查詢要求子查詢結果集必須只有一條記錄,而且查詢結果的各個值必須與參數括號里面的各個值對應。由于行子查詢本身可以通過其他語句替代,加之在一條記錄之上再做查詢沒什么實際意義,所以應用場景非常有限。
六、表子查詢(多行多列)
表子查詢一般放在 from 子句后面,充當一個小型的結果集,可以進行常規的篩選,甚至是連接查詢。但要求必須要給子查詢起別名。
案例:查詢部門編號大于2, 且工資大于5000 的員工姓名、工資、部門編號、部門名稱。
SELECT e.emp_name, e.salary, e.dept_id, d.`dept_name` FROM (SELECT `emp_name`, dept_id, salary FROM empWHERE dept_id >= 2AND salary > 5000 ) e LEFT JOIN dept d ON e.dept_id = d.`id`;整體查詢結果:
表子查詢也是比較常用的子查詢類型。
EXISTS 后面的表子查詢
exists()函數值關心參數中是否有值,如果有則輸出1, 如果沒有就是0.
SELECT EXISTS(SELECT * FROM emp)另外,EXISTS 函數還可以用于 WHERE 子句后面,含義是“當存在/不存在時執行查詢”,效果類似于 COUNT > 0 或 COUNT = 0
SELECT * FROM dept WHERE EXISTS(SELECT * FROM emp)?
SELECT * FROM dept WHERE NOT EXISTS(SELECT * FROM emp)?
七、子查詢經典案例
員工表:
部門表:
案例一:查詢工資最低的員工信息:
SELECT * FROM emp WHERE salary = (SELECT MIN(salary) FROM emp )案例二:查詢部門平均工資最低的部門信息:
SELECT * FROMdept d,(SELECT MIN(avg_sal),dept_id FROM(SELECT AVG(salary) avg_sal,dept_id FROMemp GROUP BY dept_id) sal) lowest WHERE d.`id` = lowest.dept_id ;其實這種子查詢是完全可以簡化的,比如通過排序或 LIMIT 子句等。
總結
SELECT 后面只支持標量子查詢。
FROM 后面支持表子查詢。
WHERE 或 HAVING 后面支持(重點):標量子查詢、列子查詢、行子查詢(較少)。
EXISTS 后面支持表子查詢。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的MySQL 基础 ———— 子查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: int和Integer的比较
- 下一篇: 一篇博客读懂设计模式之---动态代理与反