17/12/6 子查詢

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)
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容