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