17/12/6 子查詢
單行子查詢
- 括號內的查詢叫做子查詢,也叫內部查詢,先于主查詢的執行。
- 子查詢可以嵌入1.where 2.having 3.from子句中
練習1:
1.查詢入職日期最早的員工姓名,入職日期。
select ename, hiredate
from emp
where hiredate = (SELECT min(hiredate)
from EMP)
2.查詢工資比SMITH工資高并且工作地點在CHICAGO的員工姓名,工資,部門名稱。
select ename, sal, dept.dname
from emp
join dept on emp.deptno = dept.deptno
where sal > (select sal
from emp
where ename = 'SMITH')
and dept.loc = 'CHICAGO'
3.查詢入職日期比20部門入職日期最早的員工還要早的員工姓名,入職日期。
select ename, hiredate
from emp
where hiredate < (select min(hiredate)
from emp
where deptno = 20)
4.查詢部門人數大于所有部門平均人數的部門編號,部門名稱,部門人數。
select emp.deptno, dname, count(*)
from emp
join dept on dept.deptno = emp.deptno
group by emp.deptno, dname
HAVING count(*) > (select avg(count(*))
from emp
group by emp.deptno)
多行子查詢
-子查詢返回的條數,可以是一套或多條
-和多行子查詢進行比較時,需要使用多行操作符.
in:
any: 表示和子查詢的任意
一行結果進行比較,有一個滿足條件即可。
<li>< any: 表示小于子查詢結果集中的任意一個,即小于最大值就可以。
<li>> any: 反之,大于最小值即可。
<li>= any: 相當于IN。
all: 表示和子查詢的所有
行記過進行比較,每一行必須滿足條件。
<li>< all: 表示小于子查詢結果集中的所有行,即小于最小值。
<li>>all: 反之,大于最大值。
<li>=all: 無意義。
練習2
1.查詢入職日期比10部門任意一個員工晚的員工姓名、入職日期,不包括10部門員工。
select ename, hiredate
from emp
where hiredate >any (select hiredate
from emp
where deptno=10)
and deptno <> 10
2.查詢入職日期比10部門任意一個員工晚的員工姓名、入職日期,不包括10部門的員工。
select ename, hiredate
from emp
where hiredate >all (select hiredate
from emp
where deptno=10)
and deptno <> 10
3.查詢職位和10部門任意一個員工職位相同的員工姓名,職位,不包括10部門員工。
select ename, job
from emp
where job in (select job
from emp
where deptno=10)
and deptno <> 10
多列子查詢
-之前講的子查詢都是在一個條件表達式內和子查詢的一個列進行比較,多列子查詢可以在一個條件表達式內同時和子查詢的多個列進行比較。
-多列子查詢通常用IN操作符完成。
練習3
1.查詢職位及經理和10部門任意一個員工職位及經理相同的員工姓名,職位,不包括10部門員工。
select ename, job
from emp
where (job, mgr) in (select job,mgr
from emp
where deptno=10)
and deptno <> 10
2.查詢職位及經理和10部門任意一個員工職位或經理相同的員工姓名,職位,不包括10部門員工。
select ename, job
from emp
where (job in (select job
from emp
where deptno=10)
or MGR IN(select mgr
from emp
where deptno=10))
and deptno<>10
子查詢中的空值
無論什么時候只要空值有可能成為子查詢結果的一部分,就不能使用NOT IN運算符。
在from子句中使用子查詢
查詢比自己部門平均工資高的員工姓名,工資,部門編號,部門平均工資。
select a.ename, a.sal, a.deptno, b.salavg
from emp a, (select deptno, avg(sal) salavg
from emp
group by deptno) b
where a.deptno = b.deptno
and a.sal > b.salavg
練習4:
1.查詢比自己職位平均工資高的員工姓名、職位,部門名稱,職位平均工資。
select a.ename, a.job, dept.deptno, b.salavg
from emp a, dept, (select job, avg(sal) salavg
from emp
group by job) b
where a.job = b.job and a.DEPTNO = DEPT.DEPTNO
and a.sal > b.salavg
2.查詢職位和經理同員工SCOTT或BLACK完全相同的員工姓名、職位、不包括SCOTT和BLAKE本人。
方法1:多列子查詢
select ename, job
from emp
where (job, mgr) in (
select job, mgr
from emp
where ename in('SCOTT','BLAKE') )
and ename not in ('SCOTT','BLAKE')
方法2:建立一個與'SCOTT' ,'BLAKE'的職位和經理的臨時表,然后與emp建立連接,過濾掉與SCOTT 與 BLAKE 職位經理不同的行。
select ename,EMP.job
from EMP
join
(select job,mgr
from emp
where ename in ('SCOTT','BLAKE')) tempTab
on EMP.job = TEMPTAB.job and EMP.MGR = TEMPTAB.mgr
where ename not in ('SCOTT','BLAKE')
ROWNUM(偽列)
TOP-N查詢
練習5
1.查詢入職日期最早的前5名員工姓名,入職日期
SELECT ROWNUM, ename, hiredate
FROM(SELECT ename,hiredate
from emp
ORDER BY hiredate) demptab
where ROWNUM < =2
2.查詢工作在CHICAGO并且入職日期最早的前兩名員工姓名,入職日期。
SELECT ROWNUM, ename, hiredate
FROM(SELECT ename,hiredate,deptno
from emp
ORDER BY hiredate) demptab
join dept on dept.deptno = DEMPTAB.DEPTNO
where ROWNUM < =2 and dept.loc = 'CHICAGO'
分頁
練習7
1.按照每頁顯示5條記錄,分別查詢工資最高的第一頁,第二頁,第三頁信息,要求顯示員工姓名、入職日期、部門名稱、工資。
方法1:
第一頁
select *
from (select rownum rn, *
from emp join dept on emp.deptno= dept.deptno
order by sal desc) b
where rn>0 and rn <=5
方法2:
select tempTab2.ENAME,tempTab2.HIREDATE,DEPT.DNAME,TEMPTAB2.sal
from
(select rownum rn, tempTab.* from (select * from emp order by sal desc) tempTab where rownum <= 15) tempTab2
join dept on DEPT.deptno = tempTab2.deptno
where tempTab2.rn > 10
第二頁,第三頁。。。
課后作業
1.查詢工資高于編號為7782的員工工資,并且和7369號員工從事相同工作的員工的編號、姓名及工資。
select empno, ename, sal
from emp
where sal>(select sal
from emp
where empno=7782) and
job = (select job
from emp
where empno=7369)
2.查詢工資最高的員工姓名和工資。
select ename, sal
from emp
where sal = (select max(sal)
from emp)
3.查詢部門最低工資高于10號部門最低工資的部門的編號、名稱及部門最低工資。
select EMP.deptno, DEPT.dname, min(sal)
from emp
join dept on emp.deptno = dept.deptno
group by EMP.deptno, dept.dname
having min(sal) > (select min(sal)
from emp
where deptno=10)
4.查詢員工工資為其部門最低工資的員工的編號和姓名及工資。
select empno, ename, sal
from emp
join dept on emp.deptno = dept.deptno
where sal in (select min(sal)
from emp
group by deptno )
5.顯示經理是KING的員工姓名,工資。
select a.ename, a.sal
from emp a
join emp b on a.mgr = b.empno
where b.ename = 'KING'
6.顯示比員工SMITH參加工作時間晚的員工姓名,工資,參加工作時間。
select ename, sal, hiredate
from emp
where hiredate > (select hiredate
from emp
where ename = 'SMITH')
7.使用子查詢的方式查詢那些職員在NEW YORK工作。
select ename
from emp
join dept on emp.deptno = dept.deptno
where loc = 'NEW YORK'
8.寫一個查詢顯示和員工SMITH工作在同一個部門的員工姓名,雇傭日期,查詢結果中排除SMITH。
select ename, hiredate
from emp
where deptno = (select deptno
from emp
where ename='SMITH')
and ename <> 'SMITH'
9.寫一個查詢顯示其工資比全體職員平均工資高的員工編號、姓名。
select empno, ename
from emp
where sal > (select avg(sal)
from emp)
10.寫一個查詢顯示其上級領導是King的員工姓名、工資。
select a.ename, a.sal
from emp a
join emp b on a.mgr = b.empno
where a.mgr = (select empno
from emp
where ename = 'KING')
11.顯示所有工作在RESEARCH部門的員工姓名,職位。
select ename, job
from emp
join dept on emp.deptno = dept.deptno
where dept.dname = 'RESEARCH'
12.查詢每個部門的部門編號、平均工資,要求部門的平均工資高于部門20的平均工資。
select deptno, avg(sal)
from emp
group by deptno
where avg(sal) > (select avg(sal)
from emp
group by deptno)
13.查詢大于自己部門
平均工資的員工姓名,工資,所在 部門平均工資,高于部門平均工資的額度。
select e.ename, e.sal, b.avgsal, e.sal-b.avgsal
from emp e
join(select deptno,avg(sal) avgsal
from emp
group by deptno) b on e.deptno = b.deptno
where e.sal>b.avgsal
注:b.avg(sal) 必須得起別名。
14.列出至少有一個雇員的所有部門。
select deptno, count(*)
from emp
group by deptno
15.列出薪金比"SMITH"多的所有雇員.
select ename
from emp
where sal > (select sal
from emp
WHERE ename = 'SMITH')
16.列出入職日期早于其直接上級的所有雇員.
select
from emp woker
join emp manager on woker.mgr = manager
17.找員工姓名和直接上級的名字。
select woker.ename , manager.ename
from emp woker
join emp manager on woker.mgr = manager.empno
18.顯示部門名稱和人數
select dname, nvl(count(empno),0)
from emp
right join dept on emp.deptno = dept.deptno
group by dname
19.顯示每個部門的最高工資的員工
方法1:
SELECT *
FROM EMP
WHERE (DEPTNO,SAL) IN (SELECT DEPTNO,MAX(SAL) FROM EMP GROUP BY DEPTNO)
方法2:
select *
from emp a
join(select deptno, max(sal) maxsal
from emp
group by deptno) b on a.deptno = b.deptno and a.sal = b.maxsal
20.顯示出和員工號7369部門相同的員工姓名,工資
select ename, sal
from emp
where deptno = (select deptno
from emp
where empno = 7369) and empno <> 7369
21.顯示出和姓名中包含"W"的員工相同部門的員工姓名
select ename
from emp
where deptno = (select deptno
from emp
where ename like '%W%' )
22.顯示出工資大于平均工資的員工姓名,工資
select ename ,sal
from emp
where sal > (select avg(sal)
from emp )
23.顯示出工資大于本部門平均工資的員工姓名 工資
select ename, sal
from emp a
join(select DEPTNO, avg(sal) avgsal
from emp
group by deptno) b
on a.deptno = b.deptno
where a.sal > b.avgsal
24.顯示每位經理管理員工的最低工資,及最低工資者的姓名。
方法1:
select EMP.ename,EMP.sal
from EMP
join (select EMP.mgr, min(sal) minsal
from EMP
GROUP BY EMP.mgr) tempTab on EMP.mgr = tempTab.mgr and EMP.sal = tempTab.minsal
方法2:
select sal, ename
from emp
where (mgr, sal) in (select mgr, min(sal)
from emp
group by mgr)
25.顯示比工資最高的員工參加工作時間晚的員工姓名,參加
工作時間
select ename, HIREDATE
from emp
where hiredate >(select hiredate
from emp
where sal =(select max(sal) from emp))
26.顯示出平均工資最高的的部門平均工資及部門名稱
SELECT dname, avgsal
from dept d
join(select deptno, avg(sal) avgsal
from emp
GROUP BY deptno) temptab on d.deptno = TEMPTAB.DEPTNO
where avgsal = (select max(avg(sal))
from emp
group by deptno)