四、子查詢
一個select語句中包含另一個完整的select語句。
子查詢就是嵌套查詢,即SELECT中包含SELECT,如果一條語句中存在兩個,或兩個以上SELECT,那麼就是子查詢語句了。
子查詢出現的位置:
- where後,作爲條爲被查詢的一條件的一部分;
- from後,作表;
當子查詢出現在where後作爲條件時,還可以使用如下關鍵字:
- any
- all
子查詢結果集的形式:
- 單行單列(用於條件)
- 單行多列(用於條件)
- 多行單列(用於條件)
- 多行多列(用於表)
練習:
1.工資高於JONES的員工。
分析:
查詢條件:工資>JONES工資,其中JONES工資需要一條子查詢。
第一步:查詢JONES的工資
SELECT sal FROM emp WHERE ename='JONES'
第二步:查詢高於JONES工資的員工
SELECT * FROM emp WHERE sal > (${第一步})
結果:
SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename='JONES')
2、查詢與SCOTT同一個部門的員工。
第一步:查詢scott的部門
SELECT deptno FROM emp WHERE ename="scott";
第二步:查詢與SCOTT同一個部門的員工
SELECT * FROM emp WHERE deptno=(${第一步});
結果:
SELECT * FROM emp WHERE deptno=(SELECT deptno FROM emp WHERE ename="scott");
- 子查詢作爲條件
- 子查詢形式爲單行單列
3、工資高於30號部門所有人的員工信息
分析:
SELECT * FROM emp WHERE sal>(SELECT MAX(sal) FROM emp WHERE deptno=30);
查詢條件:工資高於30部門所有人工資,其中30部門所有人工資是子查詢。高於所有需要使用all關鍵字。
第一步:查詢30部門所有人工資
SELECT sal FROM emp WHERE deptno=30;
第二步:查詢高於30部門所有人工資的員工信息
SELECT * FROM emp WHERE sal > ALL (${第一步})
結果:
SELECT * FROM emp WHERE sal > ALL (SELECT sal FROM emp WHERE deptno=30)
- 子查詢作爲條件
- 子查詢形式爲多行單列(當子查詢結果集形式爲多行單列時可以使用ALL或ANY關鍵字)
4、查詢工作和工資與MARTIN(馬丁)完全相同的員工信息
分析:
查詢條件:工作和工資與MARTIN完全相同,這是子查詢
第一步:查詢出MARTIN的工作和工資
SELECT job,sal FROM emp WHERE ename='MARTIN'
第二步:查詢出與MARTIN工作和工資相同的人
SELECT * FROM emp WHERE (job,sal) IN (${第一步})
結果:
SELECT * FROM emp WHERE (job,sal) IN (SELECT job,sal FROM emp WHERE ename='MARTIN')
5、有2個以上直接下屬的員工信息
第一步:查詢出有2個以上直接下屬的員工編號
SELECT mgr FROM emp GROUP BY mgr HAVING COUNT(mgr)>=2
第二步:根據員工編號查詢出其他信息
SELECT * FROM emp WHERE empno IN (${第一步});
結果:
SELECT * FROM emp WHERE empno IN(SELECT mgr FROM emp GROUP BY mgr HAVING COUNT(mgr)>=2);
- 子查詢作爲條件
- 子查詢形式爲單行多列
5、查詢員工編號爲7788的員工名稱、員工工資、部門名稱、部門地址
分析:(無需子查詢)
查詢列:員工名稱、員工工資、部門名稱、部門地址
查詢表:emp和dept,分析得出,不需要外連接(外連接的特性:某一行(或某些行)記錄上會出現一半有值,一半爲NULL值)
條件:員工編號爲7788
第一步:去除多表,只查一張表,這裏去除部門表,只查員工表
SELECT ename, sal FROM emp e WHERE empno=7788
第二步:讓第一步與dept做內連接查詢,添加主外鍵條件去除無用笛卡爾積
SELECT e.ename, e.sal, d.dname, d.loc
FROM emp e, dept d
WHERE e.deptno=d.deptno AND empno=7788
第二步中的dept表表示所有行所有列的一張完整的表,這裏可以把dept替換成所有行,但只有dname和loc列的表,這需要子查詢。
第三步:查詢dept表中dname和loc兩列,因爲deptno會被作爲條件,用來去除無用笛卡爾積,所以需要查詢它。
SELECT dname,loc,deptno FROM dept;
第四步:替換第二步中的dept
SELECT e.ename, e.sal, d.dname, d.loc
FROM emp e, (SELECT dname,loc,deptno FROM dept) d
WHERE e.deptno=d.deptno AND e.empno=7788
- 子查詢作爲表
- 子查詢形式爲多行多列
6、自連接:自己連接自己,起別名,把自己看成多張表
求7369員工編號、姓名、經理編號和經理姓名
SELECT e1.empno , e1.ename,e2.empno AS mgrno,e2.ename
FROM emp e1, emp e2
WHERE e1.mgr = e2.empno AND e1.empno = 7369;
練習:
求各個部門薪水最高的員工所有信息
select e.* from emp e,
(select max(sal) maxsal,deptno from emp
group by deptno) a
where e.deptno = a.deptno
and e.sal =a.maxsal