1、 列出至少有一個員工的所有部門編號、名稱,并統計出這些部門的平均工資、最低工資、最高工資。
1、確定所需要的數據表:
- dept表:部門名稱;
- emp表:統計信息;
2、確定已知的關聯字段:
- emp.deptno=dept.deptno;
第一步:找出至少有一個員工的部門編號
SELECT deptno
FROM emp
GROUP BY deptno
第二步:找到部門名稱,肯定使用部門表,因為現在的數據量較小,所以可以將之前的emp表和dept表兩個進行連接,統一采用多字段分組的方式查詢;
SELECT d.deptno,d.dname
FROM emp e,dept d
WHERE e.deptno=d.deptno(+)
GROUP BY d.deptno,d.dname
第三步:統計
SELECT d.deptno,d.dname,AVG(sal),MIN(sal),MAX(sal)
FROM emp e,dept d
WHERE e.deptno=d.deptno(+)
GROUP BY d.deptno,d.dname
2、 列出薪金比“SMITH”且“ALLEN”多的所有員工的編號、姓名、部門名稱、其領導姓名。
1、確定所需要的數據表:
- emp表:查詢出“SMITH”且“ALLEN”工資;
- emp表:最終的顯示需要編號、姓名;
- emp表:領導的姓名,自身關聯;
- dept表:部門名稱;
2、確定已知的關聯字段:
- 雇員和領導:emp.mgr=emp.empno;
- 雇員和部門:emp.deptno=dept.deptno;
第一步:找出“SMITH”且“ALLEN”的工資
SELECT sal FROM emp WHERE ename IN('SMITH','ALLEN');
第二步:以上的查詢返回的多行單列的記錄,按照子查詢的要求在WHERE子句中寫合適,所以這個時候將上面的查詢作為一個子查詢出現,繼續查詢符合此要求的員工的編號、姓名。
SELECT e.empno,e.ename
FROM emp e
WHERE e.sal>ALL(SELECT salFROM empWHERE ename IN('SMITH','ALLEN'));
第三步:查詢出部門的名稱,引入部門表,同時增加消除笛卡爾積的條件
SELECT e.empno,e.ename,d.dname
FROM emp e,dept d
WHERE e.sal>ALL(
SELECT sal
FROM emp
WHERE ename IN('SMITH','ALLEN'))
AND e.deptno=d.deptno;
第四步:領導的信息需要emp表自身關聯
SELECT e.empno,e.ename,d.dname,m.ename
FROM emp e,dept d,emp m
WHERE e.sal>ALL(
SELECT sal
FROM emp
WHERE ename IN('SMITH','ALLEN'))
AND e.deptno=d.deptno
AND e.mgr=m.empno(+);
3、 列出所有員工的編號、姓名及其直接上級的編號、姓名,顯示的結果按領導年工資的降序排列。
1、確定所需要的數據表:
- emp表:員工的編號、姓名;
- emp表:領導的編號、姓名、計算年薪;
2、確定已知的關聯字段:emp.mgr=memp.empno;
SELECT e.empno,e.ename,m.empno,m.ename,(m.sal+NVL(m.comm,0))*12 income
FROM emp e,emp m
WHERE e.mgr=m.empno(+)
ORDER BY income DESC;
4、列出受雇日期早于其直接上級的所有員工的編號、姓名、部門名稱、部門位置、部門人數。
1、確定所需要的數據表:
- emp表:雇員的編號、姓名;
- emp表:求出領導的工作日期;
- dept表:部門名稱、位置;
- emp表:統計部門人數;
2、確定已知的關聯字段:
- 雇員和部門:emp.deptno=dept.deptno;
- 雇員和領導:emp.mgr=memp.empno;
第一步:列出受雇日期早于其直接上級的所有員工的編號、姓名 —— 自身關聯emp表。
SELECT e.empno,e.ename
FROM emp e,emp m
WHERE e.mgr=m.empno(+) AND e.hiredate<m.hiredate;
第二步:加入部門信息,繼續引入部門表
SELECT e.empno,e.ename,d.dname,d.loc
FROM emp e,emp m,dept d
WHERE e.mgr=m.empno(+) AND e.hiredate<m.hiredate
AND e.deptno=d.deptno;
額外提問,此時的笛卡爾積:emp表的14條 * emp表的14條 * dept表的4條;
第三步:統計部門人數,此時由于要使用統計函數,而且以上的查詢也無法再直接出現統計函數,所以使用子查詢完成
SELECT e.empno,e.ename,d.dname,d.loc,temp.count
FROM emp e,emp m,dept d,(
SELECT deptno dno,COUNT(empno) count
FROM emp
GROUP BY deptno) temp
WHERE e.mgr=m.empno(+) AND e.hiredate<m.hiredate
AND e.deptno=d.deptno
AND e.deptno=temp.dno;
當查詢顯示的時候需要統計信息,但是又不能直接使用統計函數查詢的話,通過子查詢在FROM子句之后進行統計。
5、列出部門名稱和這些部門的員工信息(數量、平均工資),同時列出那些沒有員工的部門。
1、確定所需要的數據表:
- dept表:部門的信息;
- emp表:求出所有的統計信息;
2、確定已知的關聯字段:emp.deptno=dept.deptno;
SELECT d.deptno,d.dname,d.loc,COUNT(e.empno),AVG(e.sal)
FROM emp e,dept d
WHERE e.deptno(+)=d.deptno
GROUP BY d.deptno,d.dname,d.loc;
6、列出所有“CLERK”(辦事員)的姓名及其部門名稱,部門的人數,工資等級。
1、確定所需要的數據表:
- emp表:找到辦事員的姓名;
- dept表:部門名稱;
- emp表:統計求出部門的人數;
- salgrade表:查詢工資等級;
2、確定已知的關聯字段:
- emp表和dept表:emp.deptno=dept.deptno;
- emp表和salgrade表:emp.sal BETWEEN salgrade.losal AND salgrade.hisal;
第一步:找到所有辦事員的姓名
SELECT e.ename
FROM emp e
WHERE job='CLERK';
第二步:找到部門信息,引入dept表,同時增加消除笛卡爾積的條件
SELECT e.ename,d.dname
FROM emp e,dept d
WHERE job='CLERK' AND e.deptno=d.deptno;
第三步:部門人數需要額外的統計,但是本程序的查詢里面已經不可能繼續使用COUNT()函數,所以寫子查詢統計SELECT e.ename,d.dname,temp.count
FROM emp e,dept d,(
SELECT deptno dno,COUNT(empno) count
FROM emp
GROUP BY deptno) temp
WHERE e.job='CLERK' AND e.deptno=d.deptno
AND d.deptno=temp.dno;
第四步:雇員的工資等級,繼續引入salgrade表SELECT e.ename,d.dname,temp.count,s.grade
FROM emp e,dept d,(
SELECT deptno dno,COUNT(empno) count
FROM emp
GROUP BY deptno) temp,salgrade s
WHERE e.job='CLERK' AND e.deptno=d.deptno
AND d.deptno=temp.dno
AND e.sal BETWEEN s.losal AND s.hisal;
7、列出最低薪金大于1500的各種工作及從事此工作的全部雇員人數及所在部門名稱、位置、平均工資。
1、確定所需要的數據表:
- emp表:最低薪金大于1500的工作肯定需要使用emp表統計求出,以及可以求出雇員人數;
- dept表:求出些雇員所在的部門信息;
- emp表:統計求出部門的平均工資;
2、確定已知的關聯字段:emp.deptno=dept.deptno;
第一步:使用emp表按照job分組,統計最低工資(HAVING)和人數
SELECT e.job,COUNT(e.empno)
FROM emp e
GROUP BY e.job
HAVING MIN(e.sal)>1500;
第二步:要查詢出雇員所在的部門信息,但是以上的查詢能跟dept表有關聯嗎?
以上的查詢和dept表之間并沒有關聯字段,那么如果沒有關聯字段,一定會有笛卡爾積產生,但是多表查詢必須要消除笛卡爾積,所以必須聯系;
- 以上的查詢可以和emp表的job字段關聯;
- 要引入的dept表也可以和emp表的deptno字段關聯;
SELECT temp.job,temp.count,d.dname,e.ename
FROM dept d,(
SELECT e.job job,COUNT(e.empno) count
FROM emp e
GROUP BY e.job
HAVING MIN(e.sal)>1500) temp,
emp e
WHERE e.deptno=d.deptno AND e.job=temp.job;
第三步:求出一個部門的平均工資,使用emp表在子查詢中統計SELECT temp.job,temp.count,d.dname,e.ename,res.avg
FROM dept d,(
SELECT e.job job,COUNT(e.empno) count
FROM emp e
GROUP BY e.job
HAVING MIN(e.sal)>1500) temp,
emp e,(
SELECT deptno dno,AVG(sal) avg
FROM emp
GROUP BY deptno) res
WHERE e.deptno=d.deptno AND e.job=temp.job
AND e.deptno=res.dno;
本題目之所以出的如此之復雜,目的是訓練大家尋找關聯字段的能力,但是本題目沒有任何的意義,知道就行了。
8、列出在部門“SALES”(銷售部)工作的員工姓名、基本工資、雇傭日期、部門名稱、假定不知道銷售部的部門編號。
1、確定所需要的數據表:
- emp表:員工姓名、基本工資、雇傭日期;
- dept表:找到銷售部的部門編號、部門名稱;
2、確定已知的關聯字段:emp.deptno=dept.deptno;
SELECT e.ename,e.sal,e.hiredate,d.dname
FROM emp e,dept d
WHERE e.deptno=d.deptno
AND d.dname='SALES';
9、列出薪金高于公司平均薪金的所有員工,所在部門,上級領導,公司的工資等級。
1、確定所需要的數據表:
- emp表:可以求出公司的平均薪金;
- emp表:員工的信息;
- dept表:部門的信息;
- emp表:領導的信息;
- salgrade表:工資等級;
2、確定已知的關聯字段:
- 雇員和部門:emp.deptno=dept.deptno;
- 雇員和領導:emp.mgr=memp.empno;
- 雇員和工資等級:emp.sal BETWEEN salgrade.losal AND salgrade.hisal;
第一步:求出公司的平均薪金
SELECT AVG(sal) FROM emp;
第二步:將以上的子查詢放在WHERE子句之中,作為一個查詢條件,求出滿足此條件的雇員信息。
SELECT e.empno,e.ename,e.job,e.sal
FROM emp e
WHERE e.sal>(SELECT AVG(sal) FROM emp);
第三步:找到部門的名稱
SELECT e.empno,e.ename,e.job,e.sal,d.dname,d.loc
FROM emp e,dept d
WHERE e.sal>(SELECT AVG(sal) FROM emp)AND e.deptno=d.deptno;
第四步:找到領導的信息SELECT e.empno,e.ename,e.job,e.sal,d.dname,d.loc,m.ename
FROM emp e,dept d,emp m
WHERE e.sal>(
SELECT AVG(sal) FROM emp)
AND e.deptno=d.deptno
AND e.mgr=m.empno(+);
第五步:找到工資等級SELECT e.empno,e.ename,e.job,e.sal,d.dname,d.loc,m.ename,s.grade
FROM emp e,dept d,emp m,salgrade s
WHERE e.sal>(
SELECT AVG(sal) FROM emp)
AND e.deptno=d.deptno
AND e.mgr=m.empno(+)
AND e.sal BETWEEN s.losal AND s.hisal;
10、列出與“SCOTT”從事相同工作的所有員工及部門名稱,部門人數。
1、確定所需要的數據表:
- emp表:找到SCOTT的工作;
- emp表:員工的信息;
- dept表:部門名稱;
- emp表:部門人數;
2、確定已知的關聯字段:emp.deptno=dept.deptno;
第一步:找到SCOTT的工作
SELECT job FROM emp WHERE ename='SCOTT';
第二步:以上的子查詢返回單行單列的數據,所以可以在WHERE子句中出現,以這個條件查找滿足要求的雇員信息SELECT e.empno,e.ename,e.job
FROM emp e
WHERE e.job=(
SELECT job
FROM emp
WHERE ename='SCOTT')
AND e.ename<>'SCOTT';
第三步:找到部門名稱SELECT e.empno,e.ename,e.job,d.dname
FROM emp e,dept d
WHERE e.job=(
SELECT job
FROM emp
WHERE ename='SCOTT')
AND e.ename<>'SCOTT'
AND e.deptno=d.deptno;
第四步:找到部門人數,需要統計,所以在FROM子句之中編寫SELECT e.empno,e.ename,e.job,d.dname,temp.count
FROM emp e,dept d,(
SELECT deptno dno,COUNT(empno) count
FROM emp
GROUP BY deptno) temp
WHERE e.job=(
SELECT job
FROM emp
WHERE ename='SCOTT')
AND e.ename<>'SCOTT'
AND e.deptno=d.deptno
AND temp.dno=e.deptno;
11、列出公司各個工資等級雇員的數量、平均工資。
1、確定所需要的數據表:
- emp表:統計出數據;
- salgrade表:得出工資等級;
2、確定已知的關聯字段:emp.sal BETWEEN salgrade.losal AND s.hisal;
本程序實際上就是一個多字段分組而已,唯一不同的是,將分組條件設置為salgrade表中的字段;
SELECT s.grade,s.losal,s.hisal,COUNT(e.empno),AVG(e.sal)
FROM emp e,salgrade s
WHERE e.sal BETWEEN s.losal AND s.hisal
GROUP BY s.grade,s.losal,s.hisal;
12、列出薪金高于在部門30工作的所有員工的薪金的員工姓名和薪金、部門名稱。
1、確定所需要的數據表:
- emp表:找出所有在30部門工作的雇員的工資;
- emp表:最終顯示的雇員姓名;
- dept表:找到部門名稱;
2、確定已知的關聯字段:emp.deptno=dept.deptno;
第一步:找到30部門工作的雇員的工資
SELECT sal FROM emp WHERE deptno=30;
第二步:高于30部門,使用ALL操作符,引入emp表,查詢姓名和薪金
SELECT e.empno,e.ename
FROM emp e
WHERE sal>ALL(SELECT sal FROM emp WHERE deptno=30)AND e.deptno=d.deptno;
13、列出在每個部門工作的員工數量、平均工資和平均服務期限。
1、確定所需要的數據表:
- dept表:找到部門信息;
- emp表:統計出數量、平均工資、平均服務年限;
2、確定已知的關聯字段:emp.deptno=dept.deptno;
直接將dept和emp表關聯,使用多字段分組即可,但是對于服務年限需要一個計算過程。
SELECT d.deptno,d.dname,d.loc,COUNT(e.empno),AVG(e.sal),AVG(MONTHS_BWTWEEN(SYSDATE,e.hiredate)/12) year
FROM emp e,dept d
WHERE e.deptno(+)=d.deptno
GROUP BY d.deptno,d.dname,d.loc;
14、列出所有員工的姓名、部門名稱和工資。
1、確定所需要的數據表:
- emp表:找到員工姓名;
- dept表:部門名稱;
2、確定已知的關聯字段:emp.deptno=dept.deptno;
SELECT e.ename,d.dname,e.sal
FROM emp e,dept d
WHERE e.deptno=d.deptno;
15、列出所有部門的詳細信息和部門人數。
1、確定所需要的數據表:
- emp表:統計信息;
- dept表:查詢部門信息;
2、確定已知的關聯字段:emp.deptno=dept.deptno;
SELECT d.deptno,d.dname,d.loc,COUNT(e.empno)
FROM emp e,dept d
WHERE e.deptno(+)=d.deptno
GROUP BY d.deptno,d.dname,d.loc;
16、列出各種工作的最低工資及從事此工作的雇員姓名。
1、確定所需要的數據表:
- emp表:統計出各個工作的最低工資;
- emp表:查找出雇員姓名;
第一步:按照職位統計各個職位的最低工資
SELECT job,MIN(sal) FROM emp
GROUP BY job;
第二步:將以上的查詢和emp表關聯
SELECT e.ename,e.job,e.sal
FROM emp e,(SELECT job,MIN(sal) FROM empGROUP BY job) temp
WHERE e.job=temp.job AND e.sal=temp.min;
17、列出各個部門的MANAGER(經理)的最低薪金、姓名、部門名稱、部門人數。
1、確定所需要的數據表:
- emp表:找到經理的薪金、姓名;
- dept表:部門名稱;
- emp表:統計部門人數;
2、確定已知的關聯字段:emp.deptno=dept.deptno;
第一步:找到所有部門的經理
SELECT deptno,MIN(sal)
FROM emp
WHERE job='MANAGER'
GROUP BY deptno;
第二步:找到姓名,但是以上的子查詢,不能再出現其他的字段SELECT e.ename,e.sal
FROM emp e,(
SELECT deptno dno,MIN(sal) sal
FROM emp
WHERE job=’MANAGER’
GROUP BY deptno) temp
WHERE e.deptno=temp.dno AND e.sal=temp.sal AND e.job='MANAGER';
第三步:加入部門的名稱信息SELECT e.ename,e.sal,d.dname
FROM emp e,(
SELECT deptno dno,MIN(sal) sal
FROM emp
WHERE job='MANAGER'
GROUP BY deptno) temp,dept d
WHERE e.deptno=temp.dno AND e.sal=temp.sal AND e.job='MANAGER'
AND e.deptno=d.deptno;
第四步:統計部門人數SELECT e.ename,e.sal,d.dname,res.count
18、列出所有員工的年工資,所在部門名稱,按年薪從低到高排序。
FROM emp e,(
SELECT deptno dno,MIN(sal) sal
FROM emp
WHERE job=’MANAGER’
GROUP BY deptno) temp,dept d,(
SELECT deptno dno,COUNT(empno) count
FROM emp
GROUP BY deptno) res
WHERE e.deptno=temp.dno AND e.sal=temp.sal AND e.job='MANAGER'
AND e.deptno=d.deptno AND res.dno=d.deptno;
1、確定所需要的數據表:
- emp表:統計年工資;
- dept表:部門名稱;
2、確定已知的關聯字段:emp.deptno=dept.deptno;
SELECT e.ename,e.sal*12 income,d.dname
FROM emp e,dept d
WHERE e.deptno=d.deptno
ORDER BY income;
19、查出某個員工的上級主管及所在部門名稱,并要求出這些主管中的薪水超過3000。
1、確定所需要的數據表:
- emp表:員工的信息;
- emp表:領導的信息;
- dept表:部門名稱;
2、確定已知的關聯字段:
- 雇員和部門:emp.deptno=dept.deptno;
- 雇員和領導:emp.mgr=memp.empno;
SELECT DISTINCT m.ename,d.dname,m.sal
FROM emp e,emp m,dept d
WHERE e.mgr=m.empno AND m.deptno=d.deptno AND m.sal>3000;
20、求出部門名稱中,帶‘S’字符的部門員工的工資合計、部門人數。
1、確定所需要的數據表:
- emp表:進行統計信息;
- dept表:部門名稱;
2、確定已知的關聯字段:emp.deptno=dept.deptno;
SELECT d.dname,SUM(e.sal),COUNT(e.empno)
FROM emp e,dept d
WHERE e.deptno(+)=d.deptno AND d.dname LIKE ‘%S%’
GROUP BY d.dname;
21、給任職日期超過30年或者在87年雇傭的雇員加薪,加薪原則:10部門增長10%,20部門增長20%,30部門增長30%,依次類推。
UPDATE emp SETsal=(1 + deptno/100)*sal
WHERE MONTHS_BETWEEN(SYSDATE,hiredate)/12>30OR TO_CHAR(hiredate,’yyyy’)=1987;
?
以上內容取自復雜查詢