Oracle学习笔记(二)

一、内连接

-- 内连接
   -- 举例:查询员工表和部门表的记录
   -- 笛卡尔积:员工表中的任意一条记录要和部门表中的每一条记录相关联
   select * from emp ,dept ;
   -- 避免笛卡尔积: 设置条件(从表中外键=主表主键)
   select * from emp ,dept where emp.deptno = dept.deptno; 

   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,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,d.dname ,'||',m.empno ,m.ename,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,d.dname ,s1.grade,'||',m.empno ,m.ename,d2.dname ,s2.grade
   from emp e, emp m ,dept d ,dept d2, salgrade s1 ,salgrade s2
   where e.mgr = m.empno and e.deptno = d.deptno
   and m.deptno = d2.deptno
   and e.sal between s1.losal and s1.hisal
   and m.sal between s2.losal and s2.hisal;
-- 条件表达式
   -- case  when
   /*
   case 表达式
     when 值 then 返回值
     when 值 then 返回值
     when 值 then 返回值
     when 值 then 返回值
     ....
     else 返回值
   end
   */
   -- 举例:当输入1时,返回一 ,输入2时,返回二....
   select
      case 3
        when 1 then '一'
        when 2 then '二'
        else '其他'
      end
   from dual;

   select e.empno ,e.ename,d.dname ,
   case s1.grade
     when 1 then '一级'
     when 2 then '二级'
     when 3 then '三级'
     when 4 then '四级'
     else '其他'
   end   员工工资等级  
   ,'||',m.empno ,m.ename,d2.dname ,s2.grade
   from emp e, emp m ,dept d ,dept d2, salgrade s1 ,salgrade s2
   where e.mgr = m.empno and e.deptno = d.deptno
   and m.deptno = d2.deptno
   and e.sal between s1.losal and s1.hisal
   and m.sal between s2.losal and s2.hisal;
   -- decode
   -- decode(表达式 ,key,value ,key,value,...., elsevalue)
   select e.empno ,e.ename,d.dname ,
   case s1.grade
     when 1 then '一级'
     when 2 then '二级'
     when 3 then '三级'
     when 4 then '四级'
     else '其他'
   end   员工工资等级  
   ,'||',m.empno ,m.ename,d2.dname ,
   decode(s2.grade ,4,'四级',5,'五级','其他')领导的工资等级 
   from emp e, emp m ,dept d ,dept d2, salgrade s1 ,salgrade s2
   where e.mgr = m.empno and e.deptno = d.deptno
   and m.deptno = d2.deptno
   and e.sal between s1.losal and s1.hisal
   and m.sal between s2.losal and s2.hisal;

二、外连接

-- 外连接:能显示基准表中所有的记录
   -- 举例:查询员工的上级领导
   --左外连接:select * from 左表  left join  右表 on 条件
   select e.empno ,e.ename,m.empno ,m.ename
   from emp e left join emp m 
   on e.mgr = m.empno;

   --右外连接:select * from 左表  right join  右表 on 条件
   select e.empno ,e.ename,m.empno ,m.ename
   from emp m right join emp e 
   on e.mgr = m.empno;
   --全外连接(了解):select * from 左表  full join  右表 on 条件
   select e.empno ,e.ename,m.empno ,m.ename
   from emp m full join emp e 
   on e.mgr = m.empno;
   --特殊外连接:由内连接改造来的
   -- (+) : 显示对方表中的所有记录
   select e.empno ,e.ename,m.empno ,m.ename
   from emp e , emp m 
   where e.mgr = m.empno(+);

三、子查询

子查询:在一条sql语句中包含另一条sql查询语句
   -- 外查询  内查询
   -- 举例:查询与7876工作一样的员工
   select * from emp where job = (select job from emp where empno = 7876);
   -- 举例:查询存在员工的部门信息
      -- 先查询存在员工部门编号
      select distinct deptno from emp ;
      -- 查询部门的信息: in(set): set 必须是一个固定的集合,或者是一个一列多行的结果集
      select * from dept where deptno in (10,20,30);
      select * from dept where deptno =any (10,20,30);  -- =some

      -- 标准的语句
      select * from dept where deptno in (select distinct deptno from emp);

      -- 查询每个部门的最低工资的员工信息
      -- 先查询每个部门的最低工资
      select min(sal) minsal,deptno from emp group by deptno;
      -- 查询员工信息:如果结果集是多行多列,作为一张表使用,必须取别名
      select e.empno ,e.ename ,e.sal ,e.deptno, t.minsal ,t.deptno
      from emp e,(select min(sal) minsal,deptno from emp group by deptno) t
      where e.deptno = t.deptno and t.minsal = e.sal;
      -- 查询与7790工作一样的员工信息
      select * from emp where job = (select job from emp where empno = 7790);
   -- 子查询小结
      -- 返回一个值:可以使用 = != <> <= >=
      -- 返回一列多行:使用in  ,=any ,=some  
      -- 返回多行多列:把结果集作为表使用
      -- 返回null: 不会报错

四、exists运算符

-- exists 运算符(效率较高):存在 ,只会返回两个值:true ,false
   select * from emp where exists (select * from emp where empno = 7788);
   select * from emp where 1=1;
   select * from emp where exists (select * from emp where empno = 8890);
   select * from emp where 1=2;
   -- 举例:查询存在员工的部门信息
   select * from dept where deptno in (select distinct deptno from emp); 

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

五、分页

-- 伪列:   
    --rowid 行编号: 在添加记录时生成,存储的内存地址
    select e.*,rowid from emp e where rowid= 'AAAMfPAAEAAAAAgAAA';
    -- rownum : 行号,每加载一条记录生成一个行号,行号是从1 开始,依次递增,每次递增一个        
 -- 分页
    select e.*,rownum from emp  e;
    -- 举例:查询员工表的前三条记录
    select e.*,rownum from emp  e where rownum <= 3;
    -- 举例:查询员工表的4-6条记录
    -- 先生成行号
    select e.*,rownum from emp  e
    -- 把结果集作为表使用,做条件筛选
    select t.*
    from (select e.*,rownum rn from emp  e) t
    where t.rn between 4 and 6;
    -- 举例: 查询工资最高的前三名
    -- 先工资的降序排序
    select e.* from emp e order by sal desc;
    -- 把结果集作为表使用,再生成行号
    select t.*
    from (select e.* from emp e order by sal desc) t
    where rownum <= 3
    -- 举例: 查询工资最高的 4 - 6名
    -- 先按照工资的降序排序
    select e.* from emp e order by sal desc
    -- 作为表示用,生成行号
    select t.* ,rownum rn from (select e.* from emp e order by sal desc) t
    -- 作为表示用,条件筛选
    select m.*
    from (select t.* ,rownum rn from (select e.* from emp e order by sal desc) t) m
    where m.rn between 4 and 6;
    -- 分析函数: row_number() over(排序语句)
    select t.*
    from (select e.* ,row_number() over(order by sal desc) rn from emp e)  t
    where t.rn between 4 and 6;

六、练习

 -- 查询员工的薪水大于本部门平均薪水的员工
    -- 先查询每个部门的平均薪水
    select avg(sal) , deptno from emp group by deptno;
    -- 条件筛选
    select e.empno ,e.ename ,e.sal ,e.deptno , t.avgsal ,t.deptno
    from emp e ,(select avg(sal) avgsal , deptno from emp group by deptno) t
    where e.deptno = t.deptno and e.sal > t.avgsal;  
    -- 查询每年入职的员工个数
    select count(1),to_char(hiredate ,'yyyy') hireyear from emp group by to_char(hiredate ,'yyyy');
    -- 行列转换
    select sum(c) "Total",
           avg(decode(hireyear ,'1980',c)) "1980",
           avg(decode(hireyear ,'1981',c)) "1981",
           avg(decode(hireyear ,'1982',c)) "1982",
           avg(decode(hireyear ,'1987',c)) "1987"
    from (select count(1) c,to_char(hiredate ,'yyyy') hireyear 
                 from emp group by to_char(hiredate ,'yyyy')) t

七、集合运算符

-- 交集
      select * from emp where deptno = 20
      intersect
      select * from emp where job = 'CLERK';

      select * from emp where deptno = 20 and job = 'CLERK';
   -- 并集: union all 不会去除重复的记录
      -- union会去除重复的记录 , 会触发索引
      select * from emp where deptno = 20
      union 
      select * from emp where job = 'CLERK';

      -- 不会触发索引
      select * from emp where deptno = 20 or job = 'CLERK';

   -- 差集: A   B
      -- 在A集合中出现的,在B集合中没有出现
      select * from emp where deptno = 20
      minus
      select * from emp where job = 'CLERK';

      select * from emp where job = 'CLERK'
      minus
      select * from emp where deptno = 20;
    -- 前提:两个集合:类型,顺序,个数一致即可  
    select empno ,ename from emp where deptno = 20
    union 
    select deptno ,dname from dept;

八、递归查询

--- 递归查询(单表的递归查询)(了解)
    -- 语法:
    /*
       select * from 表
       条件一: 设置起始位置
       start with 条件
       条件二: 设置关联条件,设置方向
       connect by 条件;
    */
    -- 查询某员工的领导信息,领导的领导信息,....
    select * from emp 
    start with empno = 7369
    connect by prior mgr = empno;
    -- 查询某员工的下属员工,下属的下属,....
    select * from emp 
    start with empno = 7839
    connect by  mgr = prior empno;

猜你喜欢

转载自blog.csdn.net/lr19941226/article/details/80959813