【Oracle学习】Oracle之多表查询

1.内连接

笛卡尔积: 两张表进行关联查询,得到的结果是两张表的乘积
如何去除笛卡尔积: 通过条件【外键】

主表:
从表:外键在这里,外键的值来源于主表的主键

–内连接:完全符合条件的数据才会显示

select *
from emp e,dept d
where e.deptno = d.deptno;

–案例:查询员工与他领导的信息

select *
from emp e,emp m
where e.mgr = m.empno;

–案例:在上面的基础上,查询员工的部门信息

select e.empno,e.ename,e.deptno,d.dname 员工部门名称, m.empno,m.ename 领导名称
from emp e,emp m,dept d
where e.mgr = m.empno
      and e.deptno=d.deptno;

–案例:在上面的基础上,查询领导的部门信息

select e.empno,e.ename,e.deptno,d.dname 员工部门名称, m.empno,m.ename 领导名称,m.deptno ,d2.dname 领导部门名称
from emp e,emp m,dept d,dept d2
where e.mgr = m.empno
      and e.deptno=d.deptno
      and m.deptno=d2.deptno;

–案例:在上面的基础上,显示员工的薪资级别

select e.empno,e.ename,e.deptno,d.dname 员工部门名称,e.sal,s.grade 员工薪资等级,
       m.empno,m.ename 领导名称,m.deptno ,d2.dname 领导部门名称
from emp e,emp m,dept d,dept d2,salgrade s
where e.mgr = m.empno
      and e.deptno=d.deptno
      and m.deptno=d2.deptno
      and e.sal between s.losal and s.hisal;

–案例:在上面的基础上,把薪资等级显示为中文 一级,二级…

select e.empno,e.ename,e.deptno,d.dname 员工部门名称,e.sal,s.grade 员工薪资等级,
       decode(s.grade,1,'一级',2,'二级',3,'三级','大boss级') as 中文等级,
       m.empno,m.ename 领导名称,m.deptno ,d2.dname 领导部门名称
from emp e,emp m,dept d,dept d2,salgrade s
where e.mgr = m.empno
      and e.deptno=d.deptno
      and m.deptno=d2.deptno
      and e.sal between s.losal and s.hisal;
     

2.外连接

外连接查询中,最关键是找基准表,如果是基准表,那么他的数据全部显示

外连接:
左外连接: select * from tab1 left join tab2 on 条件 : tab1是基准表
右外连接: select * from tab1 right join tab2 on 条件 : tab2是基准表

2-1 左外连接

– 案例: 查询员工与部门表的信息

select * from emp e left join dept d on e.deptno = d.deptno;

– 案例: 查询员工与他的薪资级别

select * from emp e left join salgrade s on e.sal between s.losal and s.hisal;

– 案例: 查询员工与领导的信息

select * from emp e left join emp m on e.mgr = m.empno;
2-2 右外连接
select * from emp m right join emp e on e.mgr = m.empno;

–oracle中独有外链接: 在内连接的基础上,使用 + 号
– 口诀: + 号在那边,对面的一边就是基准表

select * 
from emp e,emp m
where e.mgr = m.empno(+);

3.子查询

–【范例1】: 查询比SCOTT 用户工资高的员工
步骤:
–1)查询scott用户的工资

select * from emp where ename = 'SCOTT';
--2)把上述的查询作为一个条件
select * 
from emp
where sal > (select sal from emp where ename = 'SCOTT');

–【范例2】:查询出比雇员 7654 的工资高,同时从事和 7788 的工作一样的员工
步骤:
–1)查询7654的工资

select sal from emp where empno = 7654;

–2)查询7788的工作

select job from emp where empno = 7788;

–3)把上述的查询作为条件

select * 
from emp
where sal > (select sal from emp where empno = 7654)
      and
      job = (select job from emp where empno = 7788);
3-1 单行子查询

–查询编号为8888的员工

select *
from emp
where job = (select job from emp where empno = 8888);
3-2 多行子查询

–查询是领导的员工

select * 
from emp
where empno in (select distinct mgr from emp); -- 查询:相当于用  empno = 7902 or empno = 7698 

–查询不是领导的员工: 使用not in 一定要去空!!!

select * 
from emp
where empno not in (select distinct mgr from emp where mgr is not null);-- 相当于:  empno=7902  and  empno=7698 and empno = null

–非法使用子查询的问题 : 使用等于号的时候,返回的结果应该只有一条,下面的查询 会报错!!!

select * 
from emp
where job = (select job from emp);
3-3 exists的用法

exists(子查询) :
1)当子查询有返回值,那么就返回true
2)当子查询没有返回值,返回false

select * from emp where 1=1;
select * from emp where 1=2;

–exists 使用

select * from emp where exists(select * from dept where deptno=10);--返回true
select * from emp where exists(select * from dept where deptno=100);--返回false

–案例: 查询有员工的部门的信息
–使用in

select * 
from dept d
where d.deptno in(select distinct deptno from emp);

–使用exists

select * 
from dept d
where exists(select * from emp e where d.deptno = e.deptno);

–in exists区别: in会进行全表扫描; exists不会
–在查询的数据量很大【百万级】的时候,exists的效率高

4.分页

伪列:
ROWNUM:表示行号,实际上只是一个列,但是这个列是一个伪列,此列可以在每张表中出现。
ROWID:表中每行数据指向磁盘上的物理地址。

      for(int i=1;i<10;i++){
              System.out.println(i);
      }
      1 2 3 4 ......9

–【案例1】: 找出员工表中的第一页数据: pageSize = 3

select rownum,e.*
from emp e
where rownum <4;

–【案例2】: 找出员工表中的第二页数据: pageSize = 3 : rownum不能使用大于号 : 没查询一条数据就分配一个行号
–下面的查询是没有数据

select rownum,e.*
from emp e
where rownum >=4  and rownum <7;

–1、先找到小于7的数据

select rownum,e.*
from emp e
where rownum <7;

–2、把上述的查询当成一张表

select *
from (
      select rownum as rnum,e.*
      from emp e
      where rownum <7
      ) t
where t.rnum >=4;

【案例3】:对员工表的工资排序,由大到小,取出第二页,pageSize=3
–1、先排序

select *
from emp
order by sal desc;

-2、-把上述的查询当成一张表

select rownum,t.* 
from (
     select *
     from emp
     order by sal desc
     ) t
where rownum < 7 ;

–3、把上面的查询当成一张表

select *
from (
      select rownum as rnum,t.* 
      from (
           select *
           from emp
           order by sal desc
           ) t
      where rownum < 7 
    ) t2
where t2.rnum >=4;

5.集合运算

/*
要求:
两个集合返回的列数、列的类型、列名要一致
*/

5-1 并集

–案例: 查询工资大于1500 或者 在20号部门下的员工

–先找到大于1500
– 把两个集合联合起来
–再找到20号部门的员工

select * from emp where sal > 1500
union all  -- 有可能有重复的数据
select * from emp where deptno = 20;
select * from emp where sal > 1500
union  -- 把两个集合联合起来,还会去重
select * from emp where deptno = 20;
5-2 交集

– 案例: 找出工资大于1500 并且是 20号部门的员工

select * from emp where sal > 1500
intersect
select * from emp where deptno = 20;
5-3 差集

—范例: 1981 年入职的普通员工(不包括总裁和经理)(差集)
–1)查询1981年入职的所有员工

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

–2)查询是总裁和经理的员工

select * from emp where job = 'MANAGER' or job = 'PRESIDENT';

–3)第一步减去第二步的集合

select * from emp where to_char(hiredate,'yyyy') = '1981'
minus
select * from emp where job = 'MANAGER' or job = 'PRESIDENT';
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值