day_02
-.多表查詢
SELECT 列名,列名...
FROM 表名 表的別名,表名 表的別名...
WHERE 條件
ORDER BY 排序字段...
1.笛卡爾積:是多張表記錄的乘積
SELECT *
FROM emp,dept
wherer ename='SMITH';
SELECT * FROM emp;
SELECT * FROM dept;
SELECT ename,emp.deptno,dname
FROM emp,dept;
2.等值連接,兩張表中存在含義相同,值相等的列
起別名后原名不在生效,別名生效
SELECT *
FROM emp ,dept
WHERE emp.deptno=dept.deptno;
3.不等值連接
SELECT * FROM salgrade;
SELECT *
FROM emp a,salgrade b
--WHERE a.sal>=b.losal AND a.sal<=b.hisal;
WHERE sal BETWEEN losal AND hisal;
--查詢員工的姓名,員工的部門名稱,員工的工資等級
SELECT ename,dname,grade
FROM emp,dept,salgrade
WHERE emp.deptno=dept.deptno AND sal BETWEEN losal AND hisal;
4.自身連接
SELECT * FROM emp;
SELECT *
FROM emp a,emp b
WHERE a.mgr=b.empno;
--查詢員工的姓名,員工的部門名稱,員工的工資等級,
--員工對應的領導的姓名,領導的部門,領導的工資等級
SELECT e.ename 員工姓名,d.dname 員工部門,s.grade 員工工資等級 ,
m.ename 領導姓名,md.dname 領導部門,ms.grade 領導工資等級
FROM emp e,emp m,dept d,salgrade s,dept md,salgrade ms
WHERE e.deptno=d.deptno AND e.sal BETWEEN s.losal AND s.hisal AND
e.mgr=m.empno AND m.deptno=md.deptno AND
m.sal BETWEEN ms.losal AND ms.hisal;
5.外連接
SELECT *
FROM emp,dept
WHERE emp.deptno(+)=dept.deptno; --右連接
SELECT *
FROM emp,dept
WHERE dept.deptno=emp.deptno(+);--左連接
6.sql1999:
(01)CROSS JOIN:交叉連接,笛卡爾積
語法:tabel1 CROSS JOIN tabel2
SELECT * FROM emp CROSS JOIN dept;
=
SELECT * FROM emp,dept;
(02)NATURAL JOIN:自然連接
語法:tabel1 NATURAL JOIN tabel2
SELECT *
FROM emp NATURAL JOIN dept;
(03)join...using(公共列名) 2和3都是公共列在前
語法:TABLE JOIN table2 USING(公共列)
SELECT *
FROM emp JOIN dept USING(deptno);
(04)join...on 連接條件
語法:tabel1 JOIN table2 ON 連接條件
SELECT *
FROM emp JOIN dept ON emp.deptno=dept.deptno;
(05)LEFT JOIN ...on 連接條件 左連接左不為空
語法:table1 LEFT JOIN table2 ON 連接條件
SELECT *
FROM dept LEFT JOIN emp ON emp.deptno=dept.deptno;
(06)RIGHT JOIN ...on 連接條件 右連接右不為空
語法:table1 RIGHT JOIN table2 ON 連接條件
SELECT *
FROM dept RIGHT JOIN emp ON emp.deptno=dept.deptno;
(07)FULL join...on 連接條件
語法:table1 FULL JOIN table2 ON 連接條件
SELECT *
FROM emp e FULL JOIN emp m ON e.mgr=m.empno;
1.顯示員工SMITH的姓名,部門名稱,直接上級名稱
SELECT e.ename,d.dname,m.ename
FROM emp e,emp m,dept d
WHERE e.deptno=d.deptno AND e.mgr=m.empno AND e.ename='SMITH';
2.顯示員工姓名,部門名稱,工資,工資級別,要求工資級別大於4級。
SELECT e.ename,d.dname,e.sal,s.grade
FROM emp e,dept d,salgrade s
WHERE e.deptno=d.deptno AND e.sal BETWEEN s.losal AND s.hisal
AND s.grade>4 ;
3.顯示員工KING和FORD管理的員工姓名及其經理姓名。
SELECT e.ename,m.ename 管理的員工姓名,ms.ename 經理名
FROM emp e,emp m,emp ms
WHERE e.empno=m.mgr AND e.ename IN('KING','FORD')
AND m.mgr=ms.empno;
4.顯示員工姓名,參加工作時間,經理名,參加工作時間,
要求參加時間比經理早。
SELECT e.ename,e.hiredate,m.ename,m.hiredate
FROM emp e,emp m
WHERE e.mgr=m.empno AND e.hiredate<m.hiredate;
SELECT * FROM emp;
SELECT * FROM salgrade;
思考練習題
2.顯示30號部門的雇員所從事的不重復的工作名稱,並顯示30部門的所在地。
SELECT DISTINCT e.job,d.loc
FROM emp e,dept d
WHERE e.deptno=d.deptno AND e.deptno=30;
SELECT * FROM emp;
SELECT * FROM dept;
3.編寫一個查詢顯示能獲得獎金的雇員的姓名、部門名稱、部門所在地。
SELECT e.ename,d.dname,d.loc
FROM emp e,dept d
WHERE e.deptno=d.deptno AND NVL(comm,0)>0;
4.編寫一個查詢顯示在DALLAS工作的雇員的姓名、工作、部門編號及部門名稱。
SELECT e.ename,e.job,e.deptno,d.dname
FROM emp e,dept d
WHERE e.deptno=d.deptno AND d.loc='DALLAS';
5.創建一個查詢顯示雇員的姓名、工作、部門名稱、工資以及工資等級。
SELECT e.ename,e.job,d.dname,e.sal,s.grade
FROM emp e,dept d,salgrade s
WHERE e.deptno=d.deptno AND e.sal BETWEEN s.losal AND s.hisal;
二.分組查詢
1.分組函數:又稱為統計函數,集合函數
SUM():求和
AVG():求平均值
MAX():求最大值
MIN():求最小值
count():求個數
*:統計的表的記錄數
列名:統計該列不為null的個數
注意:統計時,不對null值進行處理
SELECT SUM(sal),AVG(sal),MAX(sal),MIN(sal),COUNT(empno)
FROM emp;
SELECT 5.
FROM 1.
WHERE 2.
GROUP BY 3.分組字段,分組字段...
HAVING 4.組過濾條件
ORDER BY 6.
from->WHERE->GROUP BY->HAVING->SELECT->ORDER BY
WHERE 與having的區別
WHERE 是在分組錢進行過濾的,where的后面不能直接使用分組函數做比較
HAVING 是在分組后進行過濾的
--安裝職務不同來分組統計工資總和,人數
SELECT job,SUM(sal),COUNT(empno)
FROM emp
GROUP BY job;
--查詢emp表中不同的 職務
SELECT DISTINCT job
FROM emp;
SELECT job--,COUNT(*)
FROM emp
GROUP BY job;
--查詢不同的領導工號的個數
SELECT COUNT(DISTINCT mgr)
FROM emp
--統計各個部門不同職務的員工薪水的總和,平均工資
SELECT deptno,job,SUM(sal),AVG(sal)
FROM emp
GROUP BY deptno,job
ORDER BY deptno;
--統計各個部門不同職務的員工薪水的總和,平均工資
--部門名稱和職務
SELECT dname,job,SUM(sal),AVG(sal)
FROM emp,dept
WHERE emp.deptno=dept.deptno
GROUP BY dname,job
ORDER BY dname;
--統計各個部門不同職務的員工薪水的總和,平均工資
--部門名稱,編號,位置和職務
SELECT dept.deptno,dname,loc,job,SUM(sal),AVG(sal)
FROM emp,dept
WHERE emp.deptno=dept.deptno
GROUP BY dept.deptno,dname,loc,job
ORDER BY dname;
--統計不同工資等級的員工人數,工資總和,工資平均值
SELECT s.grade,SUM(e.sal),round(AVG(e.sal),2),COUNT(*)
FROM emp e,salgrade s
WHERE e.sal BETWEEN s.losal AND s.hisal
GROUP BY grade;
--統計不同工資等級的員工人數,工資總和,工資平均值
--要求員工的人數大於二
SELECT s.grade,SUM(e.sal),round(AVG(e.sal),2),COUNT(*)
FROM emp e,salgrade s
WHERE e.sal BETWEEN s.losal AND s.hisal
GROUP BY grade
HAVING COUNT(*)>2;
--查詢各個部門的平均工資大於2000的部門編號和平均工資
SELECT deptno,ROUND(AVG(sal),2)
FROM emp
GROUP BY deptno
HAVING AVG(sal)>2000;
3.分組函數的嵌套
注意:當select后面的分組函數嵌套使用時 select的后面不能直接使用列名
--查詢部門平均工資最高的平均工資
SELECT MAX(round(AVG(sal)))
FROM emp
GROUP BY deptno;
課后作業
1.查詢部門平均工資在2500元以上的部門名稱及平均工資。
SELECT d.dname,round(AVG(sal),2)
FROM emp e,dept d
WHERE e.deptno=d.deptno
GROUP BY d.dname
HAVING AVG(sal)>2500;
2.查詢員工崗位中不是以“SA”開頭並且
平均工資在2500元以上的崗位及平均工資,並按平均工資降序排序。
SELECT job,round(AVG(sal),2)
FROM emp
WHERE SUBSTR(ename,1,2)!='SA'
GROUP BY job
HAVING AVG(sal)>2500
ORDER BY AVG(sal)DESC
3.查詢部門人數在2人以上的部門名稱、最低工資、最高工資,
並對求得的工資進行四舍五入到整數位。
SELECT d.dname,round(MIN(e.sal)),round(MAX(e.sal))
FROM emp e,dept d
WHERE e.deptno=d.deptno
GROUP BY e.deptno,d.dname
HAVING COUNT(e.empno)>=2;
4.查詢崗位不為SALESMAN,工資和大於等於2500
的崗位及每種崗位的工資和。
SELECT job,SUM(sal)
FROM emp
WHERE job!='SALESMAN'
GROUP BY job
HAVING SUM(sal)>=2500;
5.顯示經理號碼和經理姓名,這個經理所管理員工的最低工資,
沒有經理的KING也要顯示,不包括最低工資小於3000的,
按最低工資由高到低排序。
SELECT e.mgr,m.ename,min(e.sal)
FROM emp e,emp m
WHERE e.mgr=m.empno --OR e.ename='king'
GROUP BY e.mgr,m.ename
HAVING MIN(e.sal)>=3000
SELECT m.empno,m.ename,MIN(e.sal)
FROM emp e,emp m
WHERE e.mgr=m.empno(+)
GROUP BY m.empno,m.ename
HAVING MIN(e.sal)>=3000
ORDER BY MIN(e.sal) DESC
6.寫一個查詢,顯示每個部門最高工資和最低工資的差額。
SELECT deptno,MAX(sal)-MIN(sal)
FROM emp
GROUP BY deptno
SELECT * FROM emp;
三.子查詢
子查詢一般用()括起來
子查詢出現的位置:SELECT,FROM,WHERE,HAVING
嵌套子查詢:一個查詢語句中嵌套了另一個查詢語句:子查詢的語句可以直接運行
單列子查詢:子查詢的返回結果是單行單列的,經常用在where,having
多行子查詢:子查詢的返回結果是單列多行的,經常用在where
多列子查詢:子查詢的返回結果是多行多列的,經常用在from,WHERE
1.單列子查詢
---查詢與smith相同職務的其他員工信息
SELECT job FROM emp WHERE LOWER(ename)='smith'
SELECT *
FROM emp
WHERE job=(SELECT job FROM emp WHERE LOWER(ename)='smith') AND LOWER(ename)!='smith'
---查詢部門平均工資最高的平均工資和部門名稱
SELECT MAX(AVG(sal))
FROM emp
GROUP BY deptno;
SELECT dname,round(AVG(sal),1)
FROM emp JOIN dept ON emp.deptno=dept.deptno
GROUP BY dname
HAVING AVG(sal)=(SELECT MAX(AVG(sal))
FROM emp
GROUP BY deptno);
2.多行子查詢:
集合運算:IN
---查詢與30部門職務相同的其他部門的員工信息
SELECT DISTINCT job FROM emp WHERE deptno=30;
SELECT *
FROM emp
WHERE job IN(SELECT DISTINCT job FROM emp WHERE deptno=30) AND deptno!=30
ANY:
=ANY:相當於in
>ANY:比子查詢返回結果的最小值要大
---查詢比10部門的最低工資要高的其他部門員工信息
SELECT *
FROM emp
WHERE sal>ANY(SELECT sal
FROM emp
WHERE deptno=10) AND deptno!=10;
<ANY:比子查詢返回結果的最大值要小
---查詢比20部門的最高工資要低的其他部門的員工信息
SELECT *
FROM emp
WHERE sal<ANY(SELECT sal
FROM emp
WHERE deptno=20) AND deptno!=20;
ALL:
=ALL:不存在現象
>ALL:比子查詢的返回結果的最大值要大
---查詢比20部門的所有人薪水都高的員工信息
SELECT *
FROM emp
WHERE sal>ALL(SELECT sal FROM emp WHERE deptno=20);
<ALL:比子查詢的返回結果的最小值要小
--查詢比10部門的所有人薪水都低的員工信息
SELECT *
FROM emp
WHERE sal<ALL(SELECT sal FROM emp WHERE deptno=10);
練習二
1.查詢入職日期比10部門任意一個員工晚的
員工姓名、入職日期,不包括10部門員工
SELECT ename,hiredate
FROM emp
WHERE hiredate >ANY(SELECT hiredate
FROM emp
WHERE emp.deptno=10) AND emp.deptno!=10;
2.查詢入職日期比10部門所有員工晚的
員工姓名、入職日期,不包括10部門員工
SELECT ename,hiredate
FROM emp
WHERE hiredate>ALL(SELECT hiredate
FROM emp
WHERE emp.deptno=10);
3.查詢職位和10部門任意一個員工職位相同的
員工姓名,職位,不包括10部門員工
SELECT ename,hiredate
FROM emp
WHERE job = ANY(SELECT job
FROM emp
WHERE deptno=10) AND deptno!=10;
3.多列子查詢
--查詢與scott用戶工資和服務都匹配的其他員工的信息
SELECT *
FROM emp
WHERE sal=(SELECT sal FROM emp WHERE UPPER(ename)='SCOTT')
AND job=(SELECT job FROM emp WHERE UPPER(ename)='SCOTT')
AND UPPER(ename)!='SCOTT';
SELECT *
FROM emp
WHERE (sal,job) IN(SELECT sal,job FROM emp WHERE UPPER(ename)='SCOTT')
AND UPPER(ename)!='SCOTT';
SELECT * FROM emp WHERE empno=7902;
--查詢部門的名稱,部門人數,部門最高工資,部門的最低工資,部門最低工資的姓名
SELECT deptno,COUNT(empno),MAX(sal),MIN(sal)
FROM emp
GROUP BY deptno;
SELECT dname,t.c,t.ma,t.mi,ename
FROM dept,emp,(SELECT deptno,COUNT(empno) c,MAX(sal) ma,MIN(sal) mi
FROM emp
GROUP BY deptno) t
WHERE emp.deptno=dept.deptno AND emp.deptno=t.deptno AND sal=t.mi
--查詢職務和經理同員工SCOTT或BLAKB完全相同的員工姓名
--、職務、不包括SCOTT和BLAKB
SELECT job,mgr
FROM emp
WHERE UPPER(ename)='SCOTT' OR UPPER(ename)='BLAKB'
SELECT ename,job
FROM emp
WHERE (job,mgr) IN (SELECT job,mgr
FROM emp
WHERE UPPER(ename)='SCOTT' OR UPPER(ename)='BLAKB')
--查詢不是經理的員工姓名
SELECT ename
FROM emp
WHERE empno NOT IN(SELECT DISTINCT mgr
FROM emp
WHERE mgr IS NOT NULL);
四.分頁查詢
oracle中
1.rownum:偽劣:從1開始遞增,
---查詢emp表中的前5行記錄
SELECT *
FROM emp
WHERE ROWNUM<=5;
ROWNUM在做比較運算時,只能使用<,<=,不能使用>,>=
---查詢emp表中的第5到第10條記錄
SELECT ROWNUM r,emp.*
FROM emp;
SELECT ROWNUM ,t.*
FROM (SELECT ROWNUM r,emp.*
FROM emp) t
WHERE t.r BETWEEN 5 AND 10;
--查詢emp表中的最后5條記錄
SELECT ROWNUM,t.*
FROM (SELECT ROWNUM r,emp.* FROM emp) t
WHERE t.r>(SELECT COUNT(empno) FROM emp)-5;
--每頁顯示三條記錄,查詢第三頁和第五頁的員工信息
SELECT ROWNUM,t.*
FROM (SELECT ROWNUM r,emp.* FROM emp) t
WHERE t.r>(3-1)*3 AND t.r<=3*3 OR t.r>(5-1)*3 AND t.r<5*3;
2.topn
---查詢工資最高的員工信息
SELECT * FROM emp ORDER BY sal DESC;
SELECT *
FROM (SELECT * FROM emp ORDER BY sal DESC) t
WHERE ROWNUM<=1;
--查詢工資最高的前5位的員工信息
SELECT *
FROM (SELECT * FROM emp ORDER BY sal DESC) t
WHERE ROWNUM<=5;