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
  • 相关阅读:
    LeetCode(81): 搜索旋转排序数组 II
    2018年6月8日论文阅读
    LeetCode(80):删除排序数组中的重复项 II
    LeetCode(79): 单词搜索
    LeetCode(78):子集
    LeetCode(77):组合
    LeetCode(76): 最小覆盖子串
    LeetCode(75):分类颜色
    LeetCode(74):搜索二维矩阵
    linux 两个查找工具 locate,find
  • 原文地址:https://www.cnblogs.com/WhiperHong/p/10878241.html
Copyright © 2011-2022 走看看