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