SQL基础系列(五)——子查询
子查詢是在一個(gè)完整的查詢語(yǔ)句中,嵌套不同功能的小查詢,從而完成復(fù)雜查詢的一種編寫(xiě)形式。本部分主要介紹非關(guān)聯(lián)子查詢,關(guān)聯(lián)子查詢的適用場(chǎng)景,語(yǔ)句寫(xiě)法,執(zhí)行邏輯及相對(duì)應(yīng)的注意事項(xiàng)。
目錄
1.非關(guān)聯(lián)子查詢
1.1執(zhí)行邏輯
1.2在WHERE子句中使用子查詢
1.2.1子查詢返回一個(gè)具體數(shù)據(jù)
1.2.2子查詢返回一條數(shù)據(jù)
1.2.3子查詢返回多行單列數(shù)據(jù)
1.3在HAVING子句中使用子查詢
1.4在FROM子句中使用子查詢
2.關(guān)聯(lián)子查詢
2.1在細(xì)分的組內(nèi)進(jìn)行比較
2.2使用EXISTS,NOT EXISTS時(shí)使用關(guān)聯(lián)子查詢
1.非關(guān)聯(lián)子查詢
在SELECT子句、GROUP BY子句、HAVING子句、ORDER BY子句中均可使用子查詢語(yǔ)句,較常用的是WHERE子句、HAVING子句和FROM子句。
1.1執(zhí)行邏輯
在非關(guān)聯(lián)子查詢中,子查詢語(yǔ)句可以獨(dú)立執(zhí)行,查詢結(jié)果是一個(gè)數(shù)據(jù),一條數(shù)據(jù),或者一張臨時(shí)數(shù)據(jù)表,主查詢可使用子查詢結(jié)果進(jìn)行操作。
1.2在WHERE子句中使用子查詢
在WHERE子句中,通常使用子查詢結(jié)果作為篩選條件。
1.2.1子查詢返回一個(gè)具體數(shù)據(jù)
題目1:求table表中工資高于平均工資的數(shù)據(jù)。
在WHERE子句中不可以使用函數(shù),因此想要求大于某個(gè)統(tǒng)計(jì)值的數(shù)據(jù),不能使用如下寫(xiě)法:
🙅SELECT * FROM table WHERE salary>avg(salary);
正確的示例如下:
🙆SELECT * FROM table WHERE salary>(SELECT?avg(salary) FROM table);
在上面標(biāo)紅的子查詢語(yǔ)句中,返回結(jié)果是一個(gè)平均值,主查詢語(yǔ)句在執(zhí)行時(shí)判斷平均工資是否大于平均值,符合條件則作為查詢結(jié)果展示。
題目2:求table1表中和'ELLEN'職位一樣的數(shù)據(jù)
思路同上,使用子查詢語(yǔ)句求出'ELLEN'的職位,再將其作為篩選條件,判斷職位與其一致的數(shù)據(jù)。
🙆SELECT * FROM table1
? ? ? WHERE job=(SELECT job FROM table1 WHERE name='ELLEN');
注釋:
- 在WHERE子句中可使用多個(gè)子查詢,支持多個(gè)條件中分別使用子查詢語(yǔ)句;
- 子查詢語(yǔ)句可以進(jìn)行嵌套;?
1.2.2子查詢返回一條數(shù)據(jù)
子查詢返回一條數(shù)據(jù),即多個(gè)屬性,使用多個(gè)屬性值進(jìn)行數(shù)據(jù)判斷,示例如下:
?題目1:求table表中與'ELLEN'工作及工資均一致的數(shù)據(jù)。
題目解析:先找出'ELLEN'的工作及工資,然后判斷數(shù)據(jù)中同時(shí)和這兩個(gè)屬性一致的數(shù)據(jù)。
🙆SELECT * FROM table1
? ? ? WHERE (job,salary)=(SELECT job,salary?FROM table1 WHERE name='ELLEN');
語(yǔ)句返回的結(jié)果中包含ELLEN及與其工作和工資一致的數(shù)據(jù)。
1.2.3子查詢返回多行單列數(shù)據(jù)
此種情況下,子查詢返回多數(shù)據(jù)時(shí)一個(gè)數(shù)據(jù)的范圍,在WHERE子句中通過(guò)數(shù)據(jù)范圍進(jìn)行篩選時(shí),需用操作符IN、ANY、ALL
(1)IN
題目1:求每個(gè)部門(mén)最低工資,并查找出與最低工資相同的員工信息
🙆SELECT * FROM table1
? ? ? WHERE sal IN (SELECT min(sal) FROM?table1 GROUP BY deptno);
子查詢中返回的是每個(gè)部門(mén)的最低工資,一列多行。根據(jù)子查詢的結(jié)果,判斷工資在子查詢數(shù)據(jù)范圍內(nèi)的數(shù)據(jù)。
??:IN,或者NOT IN 后的數(shù)據(jù)范圍內(nèi)存在值為NULL的數(shù)據(jù),則查詢結(jié)果為空。
(2)ANY
題目1:求每個(gè)部門(mén)最低工資,并查找出大于任意一個(gè)部門(mén)最低工資的員工信息
🙆SELECT * FROM table1
? ? ? WHERE sal?>ANY?(SELECT min(sal) FROM?table1 GROUP BY deptno);
>ANY:大于其后數(shù)據(jù)范圍內(nèi)最小值
<ANY:小于其后數(shù)據(jù)范圍內(nèi)最大值
=ANY:效果相當(dāng)于IN
<>ANY:🙅錯(cuò)誤用法?
(3)ALL
題目1:求每個(gè)部門(mén)最低工資,并查找出比所有部門(mén)最低工資都大的員工信息
🙆SELECT * FROM table1
? ? ? WHERE sal?>ALL?(SELECT min(sal) FROM?table1 GROUP BY deptno);
<>ALL:相當(dāng)于NOT IN
>ALL:大于其后數(shù)據(jù)范圍內(nèi)的最大值
<ALL:小于其后數(shù)據(jù)范圍內(nèi)的最小值
=ALL:🙅錯(cuò)誤用法
1.3在HAVING子句中使用子查詢
在HAVING子句中使用子查詢,即對(duì)分組進(jìn)行過(guò)濾,子查詢往往返回的都是一個(gè)具體的數(shù)據(jù)(單行單列)。
題目:篩選出平均工資大于全體員工平均工資的部門(mén)
🙆SELECT deptno,?avg(sal) FROM table1
? ? ??GROUP BY?deptno
? ? ? HAVING avg(sal)>?(SELECT avg(sal) FROM?table1);
??:分組語(yǔ)句中,SELECT后只能跟分組字段、函數(shù)及常數(shù),不能使用非分組函數(shù);
解析思路:
HAVING子句中限定組的篩選條件。題目中,需計(jì)算出各部門(mén)的平均工資,并篩選出符合條件的部門(mén)(部門(mén)就是分組標(biāo)準(zhǔn))。
子查詢語(yǔ)句中,計(jì)算出部門(mén)整體的平均工資,然后將各部門(mén)的平均工資與之對(duì)比。
1.4在FROM子句中使用子查詢
FROM子句限定查詢的數(shù)據(jù)表,使用子查詢,即將子查詢的結(jié)果作為一張臨時(shí)的數(shù)據(jù)表使用。
題目:emp表:部門(mén)編號(hào)(deptno),姓名(name),工資(sal),職位(job),雇傭日期(hiredate)
篩選出公司每個(gè)員工的編號(hào),姓名,工資,職位,雇傭日期,部門(mén)最大工資,部門(mén)最小工資
題目分析:
要求的取值結(jié)果中,包含分組統(tǒng)計(jì)的內(nèi)容(部門(mén)最大最小值)及數(shù)據(jù)表其他字段。
分組情況下,SELECT子句僅可跟分組字段,函數(shù),常量。題目需要展示非分組字段。
因此,需要把分組統(tǒng)計(jì)的結(jié)果單獨(dú)查詢出作為一個(gè)數(shù)據(jù)表,將此表與原表進(jìn)行聯(lián)結(jié)。
SELECT e.deptno,e.name,e.sal,e.job,e.hiredate,t.max,t.min
FROM emp e,
? ? ? ? ? ?(SELECT deptno,max(sal) max,min(sal) min FROM emp GROUP BY deptno) t
WHERE e.deptno=t.deptno;
2.關(guān)聯(lián)子查詢
關(guān)聯(lián)子查詢:子查詢不可獨(dú)立執(zhí)行,子查詢中使用主查詢的列作為條件。先執(zhí)行外部查詢,將外部查詢出的每條數(shù)據(jù)傳遞給子查詢語(yǔ)句執(zhí)行,子查詢執(zhí)行一次返回執(zhí)行結(jié)果后,主查詢根據(jù)子查詢結(jié)果進(jìn)行決策。
2.1在細(xì)分的組內(nèi)進(jìn)行比較
題目1:根據(jù)各個(gè)部門(mén)的平均工資,查詢超過(guò)本部門(mén)平均工資的員工信息。
🙅錯(cuò)誤寫(xiě)法
🙅SELECT * FROM table1
? ? ? WHERE sal?>(SELECT avg(sal) FROM?table1 GROUP BY deptno);
錯(cuò)誤原因:在子查詢中查每個(gè)部門(mén)的平均工資,但是是多行多列的結(jié)果。WHERE條件后,當(dāng)子查詢結(jié)果為單行單列時(shí),才能進(jìn)行正常比較。
🙆正確寫(xiě)法
🙆SELECT * FROM table1 t1
? ? ? WHERE sal?>(SELECT avg(sal) FROM?table1 t2 WHERE t1.deptno=t2.deptno);
上面子查詢的語(yǔ)句為關(guān)聯(lián)子查詢,子查詢的where子句中使用了主查詢的字段列作為限定條件。
在執(zhí)行這條語(yǔ)句時(shí),取出主查詢中的一條員工數(shù)據(jù),傳入子查詢中,在子查詢中篩選此員工同部門(mén)的數(shù)據(jù),計(jì)算部門(mén)的平均工資。主查詢中將此員工工資和同部門(mén)的平均工資對(duì)比,符合條件則保留員工數(shù)據(jù)。然后再取下一個(gè)員工,重復(fù)執(zhí)行以上過(guò)程。
2.2使用EXISTS,NOT EXISTS時(shí)使用關(guān)聯(lián)子查詢
題目:用戶表customer 訂單表order?
求沒(méi)有下過(guò)訂單的客戶的信息
🙆SELECT * FROM customer c
? ? ? WHERE not exists?
?? ? ? ? ? ? ? ? ? ??(SELECT customer_id?FROM order o?WHERE c.customer_id=o.customer_id);
假設(shè)張三下了訂單,李四沒(méi)有下訂單。
那么在語(yǔ)句執(zhí)行的時(shí)候,通過(guò)外查詢語(yǔ)句取張三的信息,通過(guò)子查詢中的WHERE判斷,子查詢可取出一條數(shù)據(jù),不符合not exists,此條數(shù)據(jù)不保留。
取李四的數(shù)據(jù),通過(guò)子查詢中的where判斷,子查詢無(wú)符合條件的數(shù)據(jù),符合not exists,此條數(shù)據(jù)保留。
EXISTS,NOT EXISTS還有更復(fù)雜的用法,后續(xù)可以單獨(dú)介紹一下。看到一篇講的比較詳細(xì)的文章,大家如果有興趣可以移步至:
EXISTS,NOT EXISTS
總結(jié)
以上是生活随笔為你收集整理的SQL基础系列(五)——子查询的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 最新07高考零分作文片断
- 下一篇: Android Behavior