一起聊聊Oracle高級查詢(實例詳解)

本篇文章給大家?guī)砹岁P(guān)于oracle高級查詢的相關(guān)知識,其中包括了分組查詢、多表查詢和子查詢,希望對大家有幫助。

一起聊聊Oracle高級查詢(實例詳解)

oracle高級查詢

高級查詢在數(shù)據(jù)庫的開發(fā)過程中應用廣泛,從分組查詢、多表查詢和子查詢?nèi)齻€方面介紹Oracle的高級查詢。

分組查詢

分組查詢是按照一定的規(guī)則進行分組,分組以后數(shù)據(jù)會聚合,需要使用聚合函數(shù),但是使用聚合函數(shù)不一定要分組,分組的關(guān)鍵字是group by。

常用的聚合函數(shù)有:最大值max(),最小值min(),平均值avg(),總和sum(),統(tǒng)計個數(shù)count()

count函數(shù)使用列名時會自動忽略空值

一起聊聊Oracle高級查詢(實例詳解)

nvl函數(shù)可以防止count自動忽略空值,它的作用是當comm為空時返回0,因為0是非空,所以會進入統(tǒng)計總數(shù)。

一起聊聊Oracle高級查詢(實例詳解)

group by子查詢

在select 列表中所有未包含在聚合函數(shù)中的列都應該包含在group by子句中。

單列分組

求每個部門的平均工資,顯示部門號,部門的平均工資。

select deptno,avg(sal) from emp group by deptno order by deptno

多列分組

按部門,不同職位,統(tǒng)計員工的工資總和

select detpno,job,sum(sal) from emp group by deptno,job order by deptno

過濾分組

having子句的使用

where與having的區(qū)別

  • where子句中不能使用聚合函數(shù),先過濾后分組
  • having子句中可以使用聚合函數(shù),先分組后過濾

注意:從SQL優(yōu)化的角度上看,盡量使用where,因為where使得分組記錄數(shù)大大降低,從而提高效率。

求平均工資大于2000的部門

select deptno,avg(sal) from emp where(avg(sal)) > 2000 group by deptno

一起聊聊Oracle高級查詢(實例詳解)

where子句中不能使用聚合函數(shù),所以報錯,改成having xxx子句即可。

select deptno,avg(sal) from emp group by deptno having(avg(sal)) > 2000

在分組查詢中使用order by

求每個部門的平均工資,顯示部門號,部門的平均工資,按照工資升序排列。

select deptno,avg(sal) from emp group by deptno order by avg(sal)

也可以按列的別名排序

select deptno,avg(sal) avgsal from emp group by deptno order by avgsal

還可以按列的序號排序,平均工資是第2列

select deptno,avg(sal) from emp group by deptno order by 2

降序排列加上desc即可

select deptno,avg(sal) from emp group by deptno order by 2 desc

分組函數(shù)的嵌套

求部門平均工資的最大值

select max(avg(sal)) from emp group by deptno

group by語句增強

主要用在group by語句報表功能

每個部門,安裝不同職位,求工資總和,部門小結(jié),總結(jié)。

一起聊聊Oracle高級查詢(實例詳解)

可以使用rollup函數(shù)

select deptno,job,sum(sal) from emp group by rollup(deptno,job)

一起聊聊Oracle高級查詢(實例詳解)

再設(shè)置一下顯示格式,break on deptno表示相同的部門號只顯示一個,skip 1表示不同的部門號之間空1行。

一起聊聊Oracle高級查詢(實例詳解)

完善報表顯示

增加標題,頁碼等

ttitle col 15 ‘我的報表’ col 35 sql.pno

設(shè)置標題,空15列顯示我的報表,然后空35列顯示頁碼

col deptno heading 部門號

col job heading 職位

col sum(sal) heading 工資總額

以上3行設(shè)置列標題

break on deptno skip 1

設(shè)置顯示格式,相同的部門號只顯示一個,不同部門號之間空1行

將這些設(shè)置保存到一個sql文件(注意要改成ANSI編碼,否則會出現(xiàn)亂碼并且設(shè)置無效),然后通過get命令讀取執(zhí)行。再次執(zhí)行查詢語句,得到如下報表。如果出現(xiàn)了多頁,為了顯示美觀,可以設(shè)置一頁顯示更多的行,比如設(shè)置每頁顯示100行:set pagesize 100

一起聊聊Oracle高級查詢(實例詳解)

多表查詢

上面的例子都是從單個表中查詢數(shù)據(jù),下面開始講解從多個表中查詢數(shù)據(jù)。

為了避免笛卡爾集,可以在where加入有效的連接條件,在實際允許環(huán)境下,應避免使用笛卡爾全集。

一起聊聊Oracle高級查詢(實例詳解)

等值連接

實例:查詢員工信息,要求顯示:員工號,姓名,月薪,部門名稱

需要查詢員工表和部門表,通過部門號進行等值連接查詢,where xxx=xxx

select e.empno,e.ename,e.sal,d.dname from emp e,dept d where e.deptno=d.deptno

不等值連接

示例:查詢員工信息,要求顯示:員工號,姓名,月薪,薪水級別

需要查詢員工表和薪水等級表,通過薪水等級上下限進行不等值連接查詢。where xxx between xxx and xxx,注意:小值在between前面,大值在between后面

select e.empno,e.ename,e.sal,s.grade from emp e,salgrade s where e.sal between s.losal and s.hisal

外連接

示例:按部門統(tǒng)計員工人數(shù),要求顯示:部門號,部門名稱,人數(shù)

需要查詢部門表和員工表

以下是通過等值連接的方式查詢,雖然總?cè)藬?shù)沒有問題,但是少了一個部門,因為一個部門沒有員工。

select d.deptno 部門號,d.dname 部門名稱,count(e.empno) 人數(shù) from emp e,dept d where e.deptno=d.deptno group by d.deptno,d.dname

一起聊聊Oracle高級查詢(實例詳解)

外連接一般通過join來實現(xiàn),一張圖看懂SQL的各種join用法。

一起聊聊Oracle高級查詢(實例詳解)

使用join語句重新實現(xiàn)示例功能

select d.deptno 部門號,d.dname 部門名稱,count(e.empno) 人數(shù) from dept d left join emp e on d.deptno=e.deptno group by d.deptno,d.dname

自連接

示例:查詢員工姓名和員工的老板姓名

核心:通過別名,將同一張表視為多張表

select e.ename 員工姓名,b.ename 老板姓名 from emp e, emp b where e.mgr=b.empno

這種方式會產(chǎn)生笛卡爾集,不適合大表的查詢,可以使用層次查詢來解決。connect by xxx start with xxx

level是層次查詢提供的偽列,需要顯示使用才會查詢這個偽列。

select level,empno,ename,sal,mgr from emp connect by prior empno=mgr start with mgr is null order by 1

子查詢

子查詢語法中的小括號

必須要有小括號,書寫風格要清晰如下圖所示:

示例:查詢比FORD工資高的員工

select * from emp where sal > (select sal from emp where ename='FORD')

可以使用子查詢的位置

select,from,where,having

select位置的子查詢只能是單行子查詢,也就是只能返回一條結(jié)果

select empno,ename,sal,(select job from emp where empno='7839') job from emp

having位置的子查詢

示例:查找部門平均工資大于30號部門最大工資的部門號及其平均工資

select deptno,avg(sal) from emp group by deptno having avg(sal) > (select max(sal) from emp where deptno=30)

from位置的子查詢

查詢結(jié)果也可以當成表

select * from (select empno,ename,sal from emp)

增加1列年薪,使用sal*12得到年薪

select * from (select empno,ename,sal,sal*12 annsal from emp)

主查詢和子查詢可以不是同一張表

示例:查詢部門名稱是SALES的員工信息

使用子查詢的方式:

select * from emp where deptno=(select deptno from dept where dname='SALES')

使用多表查詢的方式:

select e.* from emp e, dept d where e.deptno=d.deptno and d.dname='SALES'

子查詢的排序

一般不在子查詢中,使用排序;但在Top-N分析問題中,必須對子查詢排序

示例:找到員工表中工資最高的前三名,如下格式:

一起聊聊Oracle高級查詢(實例詳解)

rownum,行號,oracle自動為表分配的偽列。

  • 行號永遠按照默認的順序生成
  • 行號只能使用,>=
select rownum,empno,ename,sal from (select * from emp order by sal desc) where rownum<=3

子查詢執(zhí)行順序

一般先執(zhí)行子查詢,再執(zhí)行主查詢;單相關(guān)子查詢例外。

相關(guān)子查詢示例:找到員工表中薪水大于本部門平均薪水的員工

select empno,ename,sal,(select avg(sal) from emp where deptno=e.deptno) avgsal from emp e where sal > (select avg(sal) from emp where deptno=e.deptno)

單行子查詢和多行子查詢

單行子查詢返回一個結(jié)果,只能使用單行操作符;

多行子查詢返回多個結(jié)果,只能使用多行操作符。

單行操作符:

操作符 含義
= 等于
> 大于
>= 大于等于
小于
小于等于
不等于

多行操作符:

操作符 含義
in 等于列表中的任何一個
any 和子查詢返回的任意一個值比較
all 和子查詢返回的左右值比較

單行子查詢示例1:

查詢員工信息,要求:

職位與7566員工一樣,薪水大于7782員工的薪水

select * from emp where job=(select job from emp where empno=7566) and sal >(select sal from emp where empno=7782)

單行子查詢示例2:

查詢最低工資大于20號部門最低工資的部門號和部門的最低工資

select deptno,min(sal) from emp group by deptno having min(sal) > (select min(sal) from emp where deptno=20)

多行子查詢示例:

查詢部門名稱是SALES和ACCOUNTING的員工信息

使用多行子查詢的方式:

select * from emp where deptno in (select deptno from dept where dname='SALES' or dname='ACCOUNTING')

使用多表查詢的方式:

select e.* from emp e, dept d where e.deptno=d.deptno and (d.dname='SALES' or d.dname='ACCOUNTING')

子查詢中的空值問題

查詢不是老板的員工

注意:當子查詢中包含null值時,不要使用not in。

a not in (10,20,null)

a != 10 and a != 20 and a != null, a != null 永遠不成立,所以整個表達式永遠返回false。

可以在子查詢中把null值過濾掉再使用not in。

select * from emp where empno not in (select mgr from emp where mgr is not null)

推薦教程:《Oracle教程

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊7 分享