oracle高級查詢

幕課oracle學習筆記

--!!!scott用戶

--一.分組查詢

--1.常用的分組函數:AVG(平均數),SUM,MIN,MAX,COUNT,WM_CONCAT(行轉列)

select avg(sal),sum(sal) from emp;--工資的平均值,工資的總和

select max(sal),min(sal) from emp;--工資的最大值,最小值

select count(*) from emp;--員工的總數

select count(distinct deptno) from emp;--根據部門號取重查詢

select deptno 部門號,wm_concat(ename) 部門中的員工 from emp group by deptno;--行轉列,查出各個部門的人員名字

--分組函數會自動過濾空值,使用NVL函數使分組函數無法忽略空值

select avg(comm) from emp;--平均獎金為550

select avg(nvl (comm,0)) from emp;--平均獎金為157.14

--2.分組數據:

--(1)GROUP BY子句:select a,b,c,組函數(x) from? table_name? group by a,b,c;在select列表中所有未包含在組函數中的列都應該包含在group by子句中

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

--多個列分組

select deptno,job,sum(sal) from emp group by deptno,job;--求出每個部門各個職位的工資綜合

--(2)HAVING子句:過濾分組數據

select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;--求出平局工資大于2000的部門

--where子句中不能使用分組函數,可以在having幾組中使用;

--從sql優化的角度,沒有組函數.分組函數時where和having通用,盡量使用where(效率高)

select deptno,avg(sal) from emp group by deptno having deptno=10;--10號部門的平均工資

select deptno,avg(sal) from emp where deptno=10 group by deptno ;--10號部門的平均工資

--(3)order by子句:默認升序,降序+desc

select deptno,avg(sal) 平均工資 from emp group by deptno order by 平均工資;--各部門平均工資并升序排列

select deptno,avg(sal) 平均工資 from emp group by deptno order by 2;--根據select語句的第二列排序

select deptno,avg(sal) 平均工資 from emp group by deptno order by 2 desc;

--(4)分組函數的嵌套

select max(avg(sal)) from emp group by deptno;--平均工資最高的部門的平均工資

--(5)group by語句的增強:rollup();主要應用于報表

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

select deptno,sum(sal) from emp group by deptno;

select sum(sal) from emp;--以上三句查詢與下面的增強查詢結果一致

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

--二.多表查詢

--笛卡爾積:多張表的列數相加,行數相乘所得的新表。;為了避免笛卡爾積,可以在where加入有效的連接條件

--四種連接(等值連接,不等值連接,外連接,自連接);

(1)等值連接

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

(2)不等值連接

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

或select e.empno,e.ename,e.sal,s.grade from emp e,salgrade s where e.sal>=s.losal and? e.sal<=s.hisal;

(3)外連接:把對于連接條件不成立的記錄,仍然包含在結果中;

--下列語句查詢丟失了deptno=40的部門,因為40部門人數為0

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

--左外連接:連接條件不成立時,等號左邊的仍然被包含;在連接條件左邊加 : (+)

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

--右外連接:連接條件不成立時,等號右邊的仍然被包含;在連接條件右邊加 : (+)

(4)自連接(不適合操作大表):通過別名,將同一張表視為多張表

select e.ename,b.ename from emp e,emp b where e.mgr=b.empno;--獲得員工的名字和他上級的名字

--層次查詢(解決自連接操作大表的笛卡爾積問題):某種情況下可以替代自連接,本質上是一個單表查詢;結果沒有自連接直觀

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

ps:connect by 上一層的員工號=老板號;start with 老板號為空,即子節點開始;level:偽列,代表樹形結構等級;order by 1 表示按level第一層開始排序

--三.子查詢(select語句的嵌套)

--(1)可以使用子查詢的位置:where,select,having,from

select ename from? emp where sal>(select sal from emp where ename='SCOTT');--工資比scott高的員工

select empno,ename,sal,(select job from emp where empno=7839) from? emp;--所有員工的職位都是7839的職位

select deptno,avg(sal) from emp group by deptno having avg(sal)>(select max(sal) from emp where deptno=30);--部門平均工資大于30部門工資最大值的部門

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

--(2)不可以使用子查詢的位置:group by

***錯誤提示:ORA-22818:這里不允許出現子查詢表達式**

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

--(3)*from 后面的子查詢

*******:在已知條件的基礎上得到更多的已知條件

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

select * from (select empno,ename,sal 月薪,sal*12 年薪 from emp);

--(4)主查詢,子查詢可以不是同一張表,只要子查詢的結果主查詢可以使用就可以!

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';

--理論上盡量使用多表查詢,只有一個from,只訪問一次數據庫.

--(5)一般不在子查詢中使用排序,但在TOP-N分析問題中,必須對子查詢排序

--TOP-N問題:例如薪水前三的員工

--rownum? 行號,oracle提供的偽列;永遠按照默認的順序生成(無任何條件的查詢表時的順序),只能使用<,<=;不能使用>,>=(分頁查詢時使用此特性)

--解決上述偽列默認順序導致查詢永遠是前三個員工,而非工資前三的員工的問題

--不使用原表,而使用倒序排列后的新表作為查詢表

select rownum,empno,ename,sal from (select? * from emp order by sal desc)? where rownum<=3;

--(6)一般先執行子查詢,再執行主查詢;但相關子查詢例外

--查詢員工標中薪水大于本部門平均水平的員工(相關子查詢:主查詢的中的值作為參數傳給子查詢,主查詢必須起別名)

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);

--(7)單行子查詢(返回單行記錄)只能使用單行操作符(=,>,>=,<,<=,<>)

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

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

--查詢薪水最低的員工信息

select *? from? emp where sal=(select min(sal) from emp);

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

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

--多行子查詢(返回多行記錄)只能使用多行操作符(in:等于列表中的任何一個,any:和子查詢返回的任意一個值比較,all:和子查詢返回的所有值比較)

--in:查詢部門名稱是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');--多表聯查(加括號,必須先執行or,再執行and)

--any:查詢工資比30號部門任意一個員工高的員工信息

select * from emp where sal>any(select sal from emp where deptno=30);

select * from emp where sal>(select min(sal) from emp where deptno=30);

--all:查詢工資比30部門所有員工高的員工信息

select * from emp where sal>all(select sal from emp where deptno=30);

select * from emp where sal>(select max(sal) from emp where deptno=30);

--(8)子查詢中的null值問題(主要是多行子查詢中)

--查詢不是老板的員工

select * from emp where empno not in(select mgr from emp where mgr is not null);--(子查詢中不能有空值,否則就查不到任何數據)

ps:? a not in (10,20,null)就等同于 a!=10 and a!=20 and a!=null;因為a!=null永遠為假,所有條件就永遠為假,就查不出任何結果

--四.示例

(1)分頁查詢顯示員工信息:顯示員工號,姓名,月薪(每頁顯示四條;顯示第二頁的員工;按照月薪降序排列)

--rownum偽列,始終從1開始,無法使用大于(>)和大于等于(>=)

select rownum,r,empno,ename,sal from

(select rownum r,empno,ename,sal from(select rownum,empno,ename,sal from emp order by sal desc) e1 where rownum<=8) e2

where r>=5;

(2)員工表中薪水大于本部門平均薪水的員工

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);--相關子查詢--相比多表查詢更節省cpu資源

--------------------------------------------

select e.empno,e.ename,e.sal,d.avgsal

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

where e.deptno=d.deptno and e.sal>d.avgsal;--多表聯查

(3)按部門統計員工,分別查出總人數,及1980,1981,1982,1987年入職的員工

select count(*) total,--使用函數的方式

sum(decode(to_char(hiredate,'YYYY'),'1980',1,0)) "1980",--to_char轉換出入職日期中的年

sum(decode(to_char(hiredate,'YYYY'),'1981',1,0)) "1981",--并與四位年份比較

sum(decode(to_char(hiredate,'YYYY'),'1982',1,0)) "1982",--相同則返回1,不同返回0

sum(decode(to_char(hiredate,'YYYY'),'1987',1,0)) "1987"--sum算出1和0的總和,即為該年份入職的人數

from emp;

-------------------------------------------------

select --使用子查詢+偽表dual的方式

(select count(*) from emp ) total,

(select count(*) from emp where to_char(hiredate,'yyyy')='1980') "1980",

(select count(*) from emp where to_char(hiredate,'yyyy')='1981') "1981",

(select count(*) from emp where to_char(hiredate,'yyyy')='1982') "1982",

(select count(*) from emp where to_char(hiredate,'yyyy')='1987') "1987"

from dual;

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

推薦閱讀更多精彩內容

  • 1. select * from emp; 2. select empno, ename, job from em...
    海納百川_4d26閱讀 1,939評論 0 4
  • 查詢是數據的一個重要操作。用戶發送查詢請求,經編譯軟件變異成二進制文件供服務器查詢,后返回查詢結果集給用戶,查詢會...
    產品小正閱讀 1,435評論 0 2
  • 1.簡介 數據存儲有哪些方式?電子表格,紙質文件,數據庫。 那么究竟什么是關系型數據庫? 目前對數據庫的分類主要是...
    喬震閱讀 1,776評論 0 2
  • 5.多表查詢 多表查詢 目的:從多張表獲取數據 前提:進行連接的多張表中有共同的列 等連接 通過兩個表具有相同意義...
    喬震閱讀 1,308評論 0 0
  • 我發現有很多人,都太脆弱,甚至有點矯情。他們沒有受過什么巨大的痛苦,不知道真正的痛苦的滋味,往往還抱怨自己苦,還露...
    人生如夢z閱讀 526評論 0 1