zoukankan      html  css  js  c++  java
  • Oracle数据库4--多表关联

    1. 92语法多表关联

    1.1笛卡尔积

    -- 笛卡尔积
    select *
    from emp,dept

    1.2等值连接

    -- 等值连接
    -- 需求:查询雇员的部门名称
    select e.ename,e.deptno,d.dname
    from emp e,dept d
    where e.deptno = d.deptno

    1.3不等值连接

    -- 不等值连接
    -- 查询每个雇员的薪资等级
    select e.ename,e.sal,sg.grade
    from emp e,salgrade sg
    where e.sal >= sg.losal and e.sal <= sg.hisal
    -- where e.sal between sg.losal and sg.hisal

    1.4外连接

    左外连接:左边的表作为主表,右边表作为从表,主表数据都显示,从表数据没有,用null填充,用+号表示。

    -- 左外连接(B)
    -- 需求:查询所有部门的雇员
    select *
    from dept d,emp e
    where d.deptno = e.deptno(+)

    右外连接: 右边的表作为主表,左边表作为从表,主表数据都显示,从表数据没有,用null填充,用+号表示。

    -- 右外连接(B)
    select *
    from emp e,dept d
    where e.deptno(+) = d.deptno;

    1.5自连接

    -- 查询每个雇员的上级领导
    select e.ename "雇员",m.ename "领导"
    from emp e,emp m
    where e.mgr = m.empno
    
    -- 优化king
    select e.ename "雇员",nvl(m.ename,'boss') "领导"
    from emp e,emp m
    where e.mgr = m.empno(+)

    1.6多余两张表的连接

    如果有多个表参与查询,先把t1xt2笛卡尔积得到一个大表T1,再把T1xt3笛卡尔积得到一个另外的大表T2,依次类推。

    所有的多表查询最终都是两种表的查询。

    -- 查询SCO%T管理者的薪资等级
    select e.ename,m.ename,sg.grade
    from emp e,emp m,salgrade sg
    where e.mgr = m.empno and (m.sal between sg.losal and sg.hisal) and e.ename = 'SCO%T'
    
    -- 查询雇员Scott所在部门名称和薪资等级
    select e.*,d.*,sg.*
    from emp e,dept d,salgrade sg
    where e.deptno = d.deptno and e.sal between sg.losal and sg.hisal
    and e.ename = 'SCO%T'

    2.99语法多表关联

    92语法的主要问题:

    [1]表的过滤条件和表的连接条件混合在一起,维护麻烦

    [2]数据库的数据适合变化,根据where子句的执行规则,sql语言也会相应发生变化,给维护造成一定成本。

    2.1笛卡尔积

    -- 99 笛卡尔积
    select *
    from dept d cross join emp e

    2.2自然连接

    NATURAL JOIN子句基于两个表中列名完全相同的列产生连接

    [1]两个表有相同名字的列

    [2]数据类型相同

    [3]从两个表中选出连接列的值相等的所有行

    -- [2]自然连接
    select *
    from dept d natural join emp e

    注意:自然连接最优的使用场景是:主外键关系且主外键字段只有一个。

    2.3using关键字

    using 主要用于指定连接字段。

    [1] 按照指定的字段连接两个表。

    [2] 选指定字段值相同的数据行。

    2.4on关键字指定连接条件

    自然连接的条件是基于表中所有同名列的等值连接,为了设置任意的连接条件或者指定连接的列,需要使用ON子句连个表的关联用关键字 join ,默认内连接(inner) 语法

    select filed1,fild2,…
    from table1 
    join table2 on condition1
         [join table3 on condition2]*
    -- 查询出员工的部门名称
    select *
    from dept d join emp e
    on d.deptno = e.deptno
    -- 查询scott的上级领导
    select e.ename,m.ename
    from emp e join emp m
    on e.mgr = m.empno
    where e.ename = 'SCO%T'

    2.5使用jion on 连接3张表

    -- 查询SCO%T部门名称和薪资等级
    select e.ename,d.dname,sg.grade
    from dept d join emp e on d.deptno = e.deptno 
    join salgrade sg on e.sal between sg.losal and sg.hisal
    where e.ename = 'SCO%T'
    -- 查询SCO%T的管理者名称和其管理者的薪资等级
    select e.ename,m.ename,sg.grade
    from emp e join emp m on e.mgr = m.empno
    join salgrade sg on m.sal between sg.losal and sg.hisal
    where e.ename = 'SCO%T'

    2.6外连接

    外连接在99语法中通过outer 关键字,按照主从表的位置可以分为left outer/right outer,语法:

    select filed1,field2
    from table1 left/right outer join table2 on condition1
          [left/right outer join table3 on condition2]*

    左外连接:

    -- 查询所有部门的所有员工
    select *
    from dept d left outer join emp e
    on d.deptno = e.deptno

    右外连接:

    -- 查询所有部门的所有员工
    select *
    from emp e right outer join dept d
    on e.deptno = d.deptno;

    3.子查询

    sql中查询是可以嵌套的。一个查询可以作为另外一个查询的条件、表。

    SELECT    select_list
    FROM    table
    WHERE    expr operator
            (SELECT    select_list
                 FROM    table);

    3.1单行子查询

    当子查询有单行时,可以取单行中的一个字段形成单个值用于条件比较。

    -- 查询雇员其薪资在雇员平均薪资以上
    -- [1] 查询员工的平均薪资
    select avg(e.sal) "AVGSAL"
    from emp e
    
    --[2] 查询满足条件的雇员
    select *
    from emp e
    where e.sal > (select avg(e.sal) "AVGSAL" from emp e)

    3.2多行子查询

    -- 查在雇员中有哪些人是管理者
    --【1】查询管理者
    select distinct e.mgr
    from emp e
    where e.mgr is not null
    
    --【2】查询指定列表的信息 in
    select e.*
    from emp e 
    where e.empno in (select distinct e.mgr
                             from emp e
                             where e.mgr is not null)

    多行子查询返回的结果可以作为 表 使用,通常结合in、some/any、all、exists。

    3.3from后的子查询

    -- 每个部门平均薪水的等级
    --【1】部门的平均薪资
    select e.deptno,avg(e.sal) "AVGSAL"
    from emp e
    group by e.deptno
    
    --【2】求等级
    select vt0.deptno,vt0.avgsal,sg.grade
    from (select e.deptno,avg(e.sal) "AVGSAL"
            from emp e
            group by e.deptno) VT0,salgrade sg
    where vt0.avgsal between sg.losal and sg.hisal
    -- 99 join on
    select vt0.deptno,vt0.avgsal,sg.grade
    from (select e.deptno,avg(e.sal) "AVGSAL"
            from emp e
            group by e.deptno) VT0 join salgrade sg on vt0.avgsal between sg.losal and sg.hisal

    3.4TOP-N

    把select得到的数据集提取前n条数。

    rownum:表示对查询的数据集记录的编号,从1开始。

    -- 查询前10名雇员
    select e.*,rownum
    from emp e
    where rownum <= 10

    rownum和order-by:

    -- 查询按照薪资降序,前10名雇员

    select vt0.*,rownum

    from (select e.*

         from emp e

         order by e.sal desc) VT0

    where rownum <= 10

    总结

    [1] order by 一定在整个结果集出现后才执行。

    [2] rownum 在结果集出现后才有编号。

    3.5分页

    -- 求查询6-10号的雇员
    select vt0.*
    from (select e.*,rownum "RN"
            from emp e 
            where rownum <= 10) VT0
    where vt0.rn >= 6

    求page=n,pagesize=size的数据

    =>[(n-1)*size+1,n*size]

    select vt0.*
    from (select t.*, rownum “RN”
    from table t 
    where rownum <= n*size) VT0
    where vt0.rn >= (n-1)*size+1

    3.6行转列

    要想从上表中得到类似下面的结果:

    姓名   语文  数学  英语

    张三    78    88    98

    王五    89    56    89

    select ts.name,
    sum(decode(ts.subject,'语文',ts.score)) "语文",
    sum(decode(ts.subject,'数学',ts.score)) "数学",
    sum(decode(ts.subject,'英语',ts.score)) "英语"
    from test_score ts
    group by ts.name
  • 相关阅读:
    解决ListView异步加载数据之后不能点击的问题
    android点击实现图片放大缩小 java技术博客
    关于 数据文件自增长 的一点理解
    RAC 实例不能启动 ORA1589 signalled during ALTER DATABASE OPEN
    Linux 超级用户的权利
    RAC 实例 迁移到 单实例 使用导出导入
    Shell 基本语法
    Linux 开机引导与关机过程
    RAC 实例不能启动 ORA1589 signalled during ALTER DATABASE OPEN
    Oracle RAC + Data Guard 环境搭建
  • 原文地址:https://www.cnblogs.com/WhiperHong/p/10878241.html
Copyright © 2011-2022 走看看