1. 程式人生 > >Oracle表復雜查詢

Oracle表復雜查詢

images 平均值 acl 部門 varchar2 轉換 tom 分頁 內連接

    Oracle表復雜查詢

聚合函數

max(字段值) -- 求最大值

min(字段值) -- 求最小值

sum(字段值) -- 求總和

avg(字段值) -- 求平均值

count(字段值) -- 求個數

group by 和 having 字句

group by : 用於對查詢的結果分組統計

having 子句:用於過濾分組顯示的結果

案例:

1.顯示每個部門的平均工資和最高工資?

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

2.顯示每個部門的每種崗位的平均工資和最低工資?

select avg(sal),min(sal) from emp group by deptno,job

3.顯示平均工資低於2000的部門號和它的平均工資?

select avg(sal) deptno from emp group by deptno having avg(sal) < 2000;

  多表查詢

技術分享

原理:

笛卡兒積: 在多表查詢的時候,如果不帶任何條件,則會出現笛卡兒積現象。

規定: 多表查詢的條件至少不能少於表的個數-1;

案例:

1.顯示雇員名,雇員工資及所在部門的名字?

select e.ename,e.sal, d.deptno

   from emp e,dept d

  where e.deptno = d.deptno

  order by d.deptno;

2.顯示部門號為10的部門名、員工名和工資?
select d.dname, e.ename, e.sa

   l from emp e, dept d

   where e.deptno = d.deptno and d.deptno = 10;

3.顯示各個員工的姓名,工資,及其工資的級別?

select emp.ename ,emp.sal , salgrade.grade

   from emp,salgrade

where emp.sal between salgrade.losal and salgrade.hisal;

    自連接

案例:

1.顯示“FORD”的上級?

select * from emp where emp.empno =

    (select mgr from emp where ename = ‘FORD‘);

2.顯示各員工的姓名和他上級領導的姓名?

select worker.ename, boss.ename

from emp worker ,emp boss

where worker.mgr = boss.empno;

   子查詢

定義

嵌入到其他sql語句的select語句,也叫嵌套查詢。

單行子查詢

定義: 返回一行數據的子查詢

案例:

如何顯示SMITH同一部門的所有員工?

select * from emp where emp.deptno =

(select deptno from emp where ename = ‘SMITH’) and ename != ‘SMITH‘;

  多行子查詢

定義:返回多行數據的子查詢

案例:

顯示10號部門的工作相同的員工姓名,工作?

select ename,job from emp where job in (

  select job from emp where deptno = 10);

all( 大於最大的):

如何顯示工資比30號部門高的員工的姓名、工資、部門號

  select ename,sal,deptno from emp where sal > all(select sal from emp where emp.deptno = 30);

等效於

select ename,sal,deptno from emp where sal > (

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

any( 大於最小的):

如何顯示工資比30號部門任意員工高的員工的姓名、工資、部門號

  select ename,sal,deptno from emp where sal > anyl(select sal from emp where emp.deptno = 30);

      等效於

  select ename,sal,deptno from emp where sal > (

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

  多列子查詢

  如何查詢與smith的部門和崗位完全相同的所有雇員

  select * from emp where (deptno,job) =

  (select deptno,job from emp where ename = ‘SMITH’);

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

註: “(deptno,job) =(select deptno,job ”是有順序的

  from中的子查詢

定義: 將select查詢結果當作一個虛表處理

案例:

顯示高於自己部門的平均工資的員工信息?

select t1.ename, t1.sal,t2.myavg from

emp t1,( select avg(sal) myavg ,deptno from emp group by deptno) t2

where t1.deptno = t2.deptno and t1.sal > t2.myavg;

顯示每個部門的信息(編號,名稱) 和人數?

select t1.dname, t1.deptno,t2.num from dept t1 , (select count(*) num,deptno from emp group by deptno) t2

where t1.deptno = t2.deptno(+);

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

(+) 在左表示右外連接,在右表示左外連接

  分頁查詢

mysql:

select * from 表名 where 條件 limit 從第幾條取,取幾條

sql server:

select top 4 * from 表名 where id not in (select top 4 id from 表名 where 條件)

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

排除前4條,再取4條,實際上是5-8條

oracle:

格式:

select * from (select rownum rn,t1.* from (select * from 表名 [ where 條件]) where rownum <= 末尾) t2 where t2.rn >= 開始;

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

rownum:偽列,用於顯示數據的行索引。

select * from emp where rownum > = 3

說明: 因為oracle的行索引(rownum)是從第1開始索引的,所以不能用>=(條件無法成立),可以用<=。

解決: 采取截取結果集的方式,將已經查詢好的查詢結果再進行過濾。

三層:

第一層: select * from 表名 [ where 條件] --放條件,比如排序等

第二層: select rownum rn,t1.* from (select * from 表名 [ where 條件]) where rownum <= 末尾 --決定末尾位置

第三層: select * from (select rownum rn,t1.* from (select * from 表名 [ where 條件]) where rownum <= 末尾) t2

where t2.rn >= 開始; --決定開始位置

拓展:

復制表: create table mytest as select empno,ename,sal,comm,deptno from emp;

插入表:insert into mytest(empno,ename,sal,comm,deptno) select empno,ename,sal,comm,deptno from mytest;

內連接與外連接

內連接: 笛卡兒積過濾後的連接

案例:

select * from emp inner join dept on emp.deptno = dept.deptno;

等效於

select * from emp,dept where emp.deptno = dept.deptno

外連接:

案例:

測試表

學生表:

create table stu (id number,name varchar2(32));

insert into stu values(1,’tom’);

insert into stu values(2,’jerry’);

insert into stu values(3,’jack’);

insert into stu values(4,’rose’);

成績表

create table exam(id number,grade number(6,2));

insert into exam(1,56);

insert into exam(2,76);

insert into exam(11,86);

要求1:顯示所有人的成績,如果沒有成績,也要顯示該人的姓名和id號,成績為空

select stu.id,stu.name,exam.grade from stu inner join exam on stu.id = exam.id;

結果:

技術分享

原因:在笛卡兒積連接之後,相同條件的才會匹配

左連接:select stu.id,stu.name,exam.grade from stu left join exam on stu.id = exam.id;

另一種寫法: select stu.id,stu.name,exam.grade from stu , exam where stu.id = exam.id(+);

結果:

技術分享

原因:連接後的數據以左邊表為基準,即使對應的右邊沒有數據,也要顯示為空。

要求2:顯示所有成績,如果沒有名字匹配,顯示空

右連接:select stu.id,stu.name,exam.grade from stu right join exam on stu.id = exam.id;

另一種寫法: select stu.id,stu.name,exam.grade from stu , exam where stu.id(+) = exam.id;

結果:

技術分享

原因:連接後的數據以右邊表為基準,即使對應的左邊沒有數據,也要顯示為空。

小結: 左右外連接可以互為轉換

比如:顯示所有成績,如果沒有名字匹配,顯示空

可以寫出:select stu.id,stu.name,exam.grade from exam left join stu on stu.id = exam.id;

案例3:顯示所有的成績和所有人的名字,如果沒有匹配值,就顯示空

完全外連接:兩個表查詢,不管有麽有匹配,都顯示。

select stu.id,stu.name,exam.grade from exam full outer join stu on stu.id = exam.id;

結果:

技術分享

Oracle表復雜查詢