一文了解MySQL的四大子查詢(xún)
本節(jié)將為大家?guī)?lái)MySQL標(biāo)量/單行子查詢(xún)、列子/表子查詢(xún)的講解?
一、子查詢(xún)概念子查詢(xún)指一個(gè)查詢(xún)語(yǔ)句嵌套在另一個(gè)查詢(xún)語(yǔ)句內(nèi)部的查詢(xún),這個(gè)特性從MySQL 4.1開(kāi)始引入;在特定情況下,一個(gè)查詢(xún)語(yǔ)句的條件需要另一個(gè)查詢(xún)語(yǔ)句來(lái)獲取,內(nèi)層查詢(xún)(inner query)語(yǔ)句的查詢(xún)結(jié)果,可以為外層查詢(xún)(outer query)語(yǔ)句提供查詢(xún)條件。
內(nèi)層查詢(xún)即子查詢(xún),外層查詢(xún)即主查詢(xún),只是叫法不同而已
?查詢(xún)需求:
查詢(xún)公司中工資最低的員工信息
工資最低是多少?
SELECT * FROM emp WHERE sal=(SELECT MIN(sal) FROM emp);?子查詢(xún)規(guī)范:
子查詢(xún)必須放在小括號(hào)中子查詢(xún)一般放在比較操作符的右邊,以增強(qiáng)代碼可讀性子查詢(xún)可以出現(xiàn)在幾乎所有的SELECT字句中(如:SELECT、FROM、WHERE、ORDER BY、HAVING子句)?子查詢(xún)分類(lèi):
1、根據(jù)子查詢(xún)返回的數(shù)據(jù)分類(lèi):
標(biāo)量子查詢(xún)(scalar subquery):返回1行1列一個(gè)值行子查詢(xún)(row subquery):返回的結(jié)果集是 1 行 N 列列子查詢(xún)(column subquery):返回的結(jié)果集是 N 行 1列表子查詢(xún)(table subquery):返回的結(jié)果集是 N 行 N 列子查詢(xún)可以返回一個(gè)標(biāo)量(就一個(gè)值)、一個(gè)行、一個(gè)列或一個(gè)表,這些子查詢(xún)分別稱(chēng)之為標(biāo)量、行、列和表子查詢(xún)。
2、根據(jù)子查詢(xún)和主查詢(xún)之間是否有條件關(guān)聯(lián)分類(lèi):
相關(guān)子查詢(xún):兩個(gè)查詢(xún)之間有一定的條件關(guān)聯(lián)(相互聯(lián)系)不相關(guān)子查詢(xún):兩個(gè)查詢(xún)之間沒(méi)有條件關(guān)聯(lián)(相互獨(dú)立)3、為了方便,對(duì)于在何處使用子查詢(xún)給大家給出幾點(diǎn)個(gè)人建議:
子查詢(xún)出現(xiàn)在WHERE子句中:此時(shí)子查詢(xún)返回的結(jié)果一般都是單列單行、單行多列、多行單列子查詢(xún)出現(xiàn)在HAVING子句中:此時(shí)子查詢(xún)返回的都是單行單列數(shù)據(jù),同時(shí)為了使用統(tǒng)計(jì)函數(shù)操作子查詢(xún)出現(xiàn)在FROM子句中:此時(shí)子查詢(xún)返回的結(jié)果圖一般都是多行多列,可以按照一張數(shù)據(jù)表(臨時(shí)表)的形式操作二、標(biāo)量/單行子查詢(xún)、列子/表子查詢(xún)??標(biāo)量子查詢(xún)子查詢(xún)返回的是單行單列的數(shù)據(jù),就是一個(gè)值
查詢(xún)出基本工資比ALLEN低的全部員工信息
SELECT * FROM emp WHERE sal<(SELECT sal FROM emp WHERE eanme='ALLEN');查詢(xún)基本工資高于公司平均工資的全部員工信息
SELECT * FROM emp WHERE sal>(SELECT AVG(sal) FROM emp);查詢(xún)出與ALLEN從事同一工作,并且基本工資高于員工編號(hào)為7521的全部員工信息
SELECT * FROM emp WHERE job=(SELECT job FROM emp WHERE ename='ALLEN') AND sal>(SELECT sal FROM emp WHERE empno=7521)#把ALLEN自己去掉AND ename<>'ALLEN';?效果如下:
子查詢(xún)返回的是單行多列的數(shù)據(jù),就是一條記錄
查詢(xún)與SCOTT從事統(tǒng)一工作且工資相同的員工信息
SELECT * FROM emp WHERE (job,sal)=(SELECT job,sal FROM emp WHERE ename='SCOTT')AND ename<>'SCOTT';查詢(xún)與員工編號(hào)為7566從事統(tǒng)一工作且領(lǐng)導(dǎo)相同的全部員工信息
SELECT * FROM emp WHERE (job,mgr)=(SELECT job,mgr FROM emp WHERE empno=7566)AND emp<>7566;?效果如下:
子查詢(xún)返回的是多行單列的數(shù)據(jù),就是一列數(shù)據(jù)。多行子查詢(xún)也稱(chēng)為集合比較子查詢(xún),
在使用多行子查詢(xún)需要使用多行比較操作符:
操作符含義IN等于列表中的任意一個(gè)ANY需要和單行比較操作符一起使用(>、<、=、<>…),與子查詢(xún)結(jié)果中任何一個(gè)值比較,一個(gè)成立ALL需要和單行比較操作符一起使用(>、<、=、<>…),和子查詢(xún)返回的所有值比較,同時(shí)成立SOME實(shí)際上是ANY的別名,作用相同,一般用ANYIN操作符
IN 運(yùn)算符用來(lái)判斷表達(dá)式的值是否位于給出的列表中;如果是,返回值為 1,否則返回值為 0。
NOT IN 的作用和 IN 恰好相反,NOT IN 用來(lái)判斷表達(dá)式的值是否不存在于給出的列表中;如果不是,返回值為 1,否則返回值為 0。
查詢(xún)出與每個(gè)部門(mén)中最低工資相同的員工信息
按照部門(mén)分組,統(tǒng)計(jì)每個(gè)部門(mén)的最低工資根據(jù)最低工資查詢(xún)出員工信息SELECT * FROM emp WHERE sal IN(SELECT MIN(sal) FROM emp GROUP BY deptno)AND deptno IS NOT NULL;ANY操作符
ANY關(guān)鍵字是一個(gè)MySQL運(yùn)算符,如果子查詢(xún)條件中ANY的比較結(jié)果為T(mén)RUE,則它會(huì)返回布爾值TRUE 。
查詢(xún)工資比任何管理工資都要高的員工信息
查找出每個(gè)管理的薪資每個(gè)員工的薪資與每個(gè)管理的薪資比較SELECT * FROM emp WHERE sal >ANY(SELECT MIN(sal) FROM emp WHERE job='MANAGER' GROUP BY deptno);ALL操作符
ALL關(guān)鍵字是一個(gè)MySQL運(yùn)算符,如果子查詢(xún)條件中ALL的比較結(jié)果為T(mén)RUE,則它會(huì)返回布爾值TRUE 。
案例同ANY操作符
?效果如下:
子查詢(xún)返回的是多行多列的數(shù)據(jù),就是一個(gè)表格,必須使用 IN、ANY 和 ALL 操作符對(duì)子查詢(xún)返回的結(jié)果進(jìn)行比較
?綜合練習(xí):
在emp表中,得到與10號(hào)部門(mén)任何一個(gè)員工入職年份和領(lǐng)導(dǎo)相同的員工信息(用在where子句中)
需要用到DATE_FORMAT(hiredate,'%Y')將入職日期轉(zhuǎn)換為年份
SELECT * FROM empWHERE (DATE_FORMAT(hiredate,'%Y'),mgr) IN (SELECT DATE_FORMAT(hiredate,'%Y') hiryear,mgr FROM emp WHERE deptno=10);查詢(xún)出每個(gè)部門(mén)的編號(hào)、名稱(chēng)、位置、部門(mén)人數(shù)、平均工資(用在from子句中)
以前學(xué)的多表聯(lián)合查詢(xún)——-emp、dept
用子查詢(xún)聯(lián)合查詢(xún)
SELECT d.deptno,d.dname,d.loc,COUNT(e.deptno),ROUND(AVG(sal),2) FROMdept d LEFT JOIN emp eON e.deptno=d.deptnoGROUP BY d.deptno,d.dname,d.loc;SELECT dept.deptno,dept.dname,dept.loc,d.count,d.avgsal FROM dept LEFT JOIN (SELECT deptno,COUNT(*) count,AVG(sal) avgsal FROM emp GROUP BY deptno) dON dept.deptno=d.deptno;查詢(xún)出所有在’SALES’部門(mén)工作的員工編號(hào)、姓名、基本工資、獎(jiǎng)金、職位、雇傭日期、部門(mén)的最高和最低工資。(where和from子句同時(shí)使用)
#1SELECT e.empno,e.ename,e.sal,e.comm,e.job,e.hiredate,minsal,maxsal,e.deptno FROM emp e JOIN (SELECT deptno,MIN(sal) minsal,MAX(sal) maxsal FROM emp GROUP BY deptno) tdON e.deptno=td.deptno AND e.deptno=(SELECT deptno FROM dept WHERE dname='SALES');#2SELECT e.empno,e.ename,e.sal,e.comm,e.job,e.hiredate,minsal,maxsal,e.deptno FROM emp e JOIN (SELECT deptno,MIN(sal) minsal,MAX(sal) maxsal FROM emp GROUP BY deptnoHAVING deptno=(SELECT deptno FROM dept WHERE dname='SALES')) tdON e.deptno=td.deptno;查詢(xún)出比‘ALLEN’或‘CLACRK’薪資多的所有員工的編號(hào)、姓名、基本工資、部門(mén)名稱(chēng)、領(lǐng)導(dǎo)姓名、部門(mén)人數(shù)。
#隱式方式SELECT e.empno,e.ename,e.sal,d.dname,me.ename 領(lǐng)導(dǎo),temp.count FROM emp e,dept d,emp me,(SELECT deptno,COUNT(deptno) count FROM emp e GROUP BY deptno) tempWHERE e.deptno=d.deptno AND e.mgr=me.empno AND temp.deptno=e.deptnoAND e.sal >ANY(SELECT sal FROM emp WHERE ename IN('ALLEN','CLARK'))AND e.ename NOT IN('ALLEN','CLARK');#顯示方式SELECT e.empno,e.ename,e.sal,d.dname,me.ename 領(lǐng)導(dǎo),temp.count FROM emp e JOIN dept d ON e.deptno=d.deptnoLEFT JOIN emp me ON e.mgr=me.empnoJOIN (SELECT deptno,COUNT(deptno) count FROM emp e GROUP BY deptno) temp ON temp.deptno=e.deptnoAND e.sal >ANY(SELECT sal FROM emp WHERE ename IN('ALLEN','CLARK'))AND e.ename NOT IN('ALLEN','CLARK');列出公司各個(gè)部門(mén)的經(jīng)理(假設(shè)每個(gè)部門(mén)只有一個(gè)經(jīng)理,job為‘MANAGER’)的姓名、薪資、部門(mén)名稱(chēng)、部門(mén)人數(shù)、部門(mén)平均工資。
#隱式方式SELECT e.ename,e.sal,d.dname,temp.count,temp.avgsalFROM emp e,dept d,(SELECT deptno, COUNT(deptno) count,AVG(sal) avgsal FROM emp GROUP BY deptno) temp WHERE job='MANAGER' AND e.deptno=d.deptno AND temp.deptno=e.deptno; #顯示方式SELECT e.ename,e.sal,d.dname,temp.count,temp.avgsalFROM emp e JOIN dept d ON e.deptno=d.deptno JOIN (SELECT deptno, COUNT(deptno) count,AVG(sal) avgsal FROM emp GROUP BY deptno) temp ON temp.deptno=e.deptno AND job='MANAGER';查詢(xún)出所有薪資高于公司平均薪資的員工編號(hào)、姓名、基本工資、職位、雇傭日期、所在部門(mén)名稱(chēng)、部門(mén)位置、上級(jí)領(lǐng)導(dǎo)姓名、工資等級(jí)、部門(mén)人數(shù)、平均工資、平均服務(wù)年限。
#隱式方式SELECT e.empno,e.ename,e.sal,e.job,e.hiredate,d.dname,d.loc,me.ename 領(lǐng)導(dǎo),s.grade,temp.count,temp.avgsal,temp.avgyearFROM emp e,dept d,emp me,salgrade s,(SELECT deptno,COUNT(deptno) count,AVG(sal) avgsal,AVG(TIMESTAMPDIFF(MONTH,hiredate,CURDATE())/12) avgyear FROM emp GROUP BY deptno) temp WHERE e.deptno=d.deptno AND e.sal>(SELECT AVG(sal) FROM emp)AND e.mgr=me.empnoAND e.sal BETWEEN s.losal AND s.hisalAND temp.deptno=e.deptno;#顯示方式SELECT e.empno,e.ename,e.sal,e.job,e.hiredate,d.dname,d.loc,me.ename 領(lǐng)導(dǎo),s.grade,temp.count,temp.avgsal,temp.avgyearFROM emp e JOIN dept d ON e.deptno=d.deptno AND e.sal>(SELECT AVG(sal) FROM emp)LEFT JOIN emp me ON e.mgr=me.empnoJOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisalJOIN (SELECT deptno,COUNT(deptno) count,AVG(sal) avgsal,AVG(TIMESTAMPDIFF(MONTH,hiredate,CURDATE())/12) avgyear FROM emp GROUP BY deptno) temp ON temp.deptno=e.deptno;?? 子查詢(xún)?cè)试S結(jié)構(gòu)化的查詢(xún),這樣就可以把一個(gè)查詢(xún)語(yǔ)句的每個(gè)部分隔開(kāi)。??子查詢(xún)提供了另一種方法來(lái)執(zhí)行有些需要復(fù)雜的join和union來(lái)實(shí)現(xiàn)的操作。??在許多人看來(lái),子查詢(xún)可讀性較高。 而實(shí)際上,這也是子查詢(xún)的由來(lái)。
到此這篇關(guān)于一文了解MySQL的四大子查詢(xún)的文章就介紹到這了,更多相關(guān)MySQL 子查詢(xún)內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. 記一次mariadb數(shù)據(jù)庫(kù)無(wú)法連接2. sqlserver給表添加新字段、給表和字段添加備注、更新備注及查詢(xún)備注(sql語(yǔ)句)3. Microsoft Office Access添加圖片的方法4. mysql 大表批量刪除大量數(shù)據(jù)的實(shí)現(xiàn)方法5. 一文帶你搞懂MySQL的MVCC機(jī)制6. 經(jīng)驗(yàn)總結(jié):DB2數(shù)據(jù)庫(kù)功能及性能使用方法7. MySQL實(shí)現(xiàn)數(shù)據(jù)更新的示例詳解8. SQLite3數(shù)據(jù)庫(kù)的介紹和使用教程(面向業(yè)務(wù)編程-數(shù)據(jù)庫(kù))9. 為SQLite3提供一個(gè)ANSI到UTF8的互轉(zhuǎn)函數(shù)10. Mysql/MariaDB啟動(dòng)時(shí)處于進(jìn)度條狀態(tài)導(dǎo)致啟動(dòng)失敗的原因及解決辦法
