Oracle之多表查询

来源:互联网 发布:东华理工行知分院学费 编辑:程序博客网 时间:2024/05/22 15:07

多表查询 SQL1999语法对多表查询的支持
   之前查询的时候都是使用一张表的数据,如果现在查询的是一张以上的表,就称之为多表查询,
   
   多表查询语法如下:
   SELECT(DISTINCT)*|查询列1 别名1,查询列2 别名2...
   FROM 表名称1 别名1,表名称2 别名2
   (WHERE 条件)
   (ORDER BY 排序字段 ASC|DESC,排序字段 ASC|DESC)
   
   范例:下面使用了多表查询 同时查询emp 和dept表
     SELECT * FROM emp,dept;
     但是从查询结果上发现数据时56条 ,emp一共14条记录 dept表为4条记录
     SELECT COUNT(*) FROM emp; 14条记录
     SELECT COUNT(*) FROM dept; 4条记录
     我们发现56=14*4条 这种无条件的查询会产生重复数据(笛卡尔积)如果表的数据越多,
     笛卡尔积就会越大,如果现在有5张表,每张10000条记录,则笛卡尔积为10000的5次方,
     要想去掉笛卡尔积则必须使用字段进行关联操作,
     
     在emp表中 我们发现存在一个deptno的字段,在dept表中也存在deptno的字段,
     而且发现emp表中的deptno的取值范围都在dept表中的deptno的取值范围中
     emp 中的deptno =dept中的deptno属于关联字段
     
     在多表查询中加入WHERE语句中,就可以消除笛卡尔积。
   范例:修改之前的操作
     SELECT * FROM emp,dept
     WHERE emp.deptno=dept.deptno;
     (字段前要加表名 区分字段,如果表名称太长时候,使用不方便 我们一般使用表别名来代替全名)
     修改后的最终SQL语句为:
     SELECT * FROM emp e,dept d
     WHERE e.deptno=d.deptno;
     
 范例:要求查询出雇员的编号、雇员的姓名、部门的编号、部门名称及部门位置;
     
     分析:由于不是查询所有信息所以不能使用* 只能使用固定列
     此查询涉及到2张表,是多表查询,关键是要确认好WHERE子句的条件
     
     SELECT e.empno ,e.ename,d.deptno,d.dname,d.loc
     FROM emp e,dept d
     WHERE e.deptno=d.deptno
     ORDER BY d.deptno;
 
 范例:要求查询出每个雇员的姓名、工作、雇员的直接上级领导的姓名
     分析:此要求是一张表之间的查询 2个字段 empno 和 mgr 相关联
     (这个可能涉及到后期继承的子类和父类在数据库中的表格式建立相关)
     属于表的内连接查询,可以为一张表起2个别名来实现
     SELECT e.ename,e.job,m.ename
     FROM emp e, emp m
     WHERE e.mgr=m.empno;
     查询的结果 是13条 经过检查我们发现 有一个员工KING 他是总裁 没有上级领导
     所以没能查询出来,对于上级领导是空值的员工 如果我们也要列举出来应该怎么查询呢?
     此时我们要利用到 外连接来查询
     
     SELECT e.ename,e.job,m.ename
     FROM emp e, emp m
     WHERE e.mgr=m.empno(+);
     关于外连接 +号在左边我们称它为右连接,右边为左外连接,后面我会详细分析
     
范例:要求进一步扩展之前的程序 将雇员所在部门名称同时列出
   部门名称在dept表中存在定义 所以涉及了3张表
   SELECT e.ename,e.job,m.ename,d.dname
    FROM emp e, emp m,dept d
    WHERE e.mgr=m.empno(+) and e.deptno(+)=d.deptno;

思考: 现在要求查询每个雇员的姓名、工资、部门名称、工资在公司的等级,及其领导的姓名及工资所在公司的等级
      工资等级表的内容: grade 工资等级 losal 最低工资 hisal最高工资
 
   分解:先查询出每个雇员的姓名、工资、部门名称、工资在公司的等级然后再关联 领导
   SELECT e.ename, e.sal, d.dname,s.grade
   FROM emp e,dept d,salgrade s
   WHERE e.deptno=d.deptno and e.sal between s.losal and s.hisal;

SQL语句如下:
   SELECT e.ename 员工姓名,e.sal 员工工资,d.dname 部门名称,es.grade 员工工资等级,
        m.ename 领导姓名,m.sal 领导工资,ms.grade 领导工资等级
   FROM emp e,emp m,dept d,salgrade es,salgrade ms
   WHERE e.mgr=m.empno and e.deptno=d.deptno and e.sal between es.losal
      and es.hisal and m.sal between ms.losal and ms.hisal;

进一步思考:现在要求按照以下的样式显示工资等级
1、第五等工资
2、第四等工资
3、第三等工资
4、第二等工资
5、第一等工资

此时由于是针对不同的等级数 进行选择操作 可以使用通用函数中的DECODE()函数 完善的SQL语句如下:

     SELECT e.ename 员工姓名,e.sal 员工工资,d.dname 部门名称,
         DECODE(es.grade,1,'第五等工资',2,'第四等工资',3,'第三等工资',4,'第二等工资',5,'第一等工资')
         员工工资等级,m.ename 领导姓名,m.sal 领导工资,DECODE(ms.grade,1,'第五等工资',2,'第四等工资',3,
         '第三等工资',4,'第二等工资',5,'第一等工资')领导工资等级
   FROM emp e,emp m,dept d,salgrade es,salgrade ms
   WHERE e.mgr=m.empno and e.deptno=d.deptno and e.sal between es.losal
      and es.hisal and m.sal between ms.losal and ms.hisal;

4.2 左右连接

 现在dept表中存在 四条部门数据
 现在将emp 和 dept表关联查询,查询一下每个部门的员工
 SELECT e.empno,e.ename,d.deptno,d.dname,d.loc
 FROM emp e, dept d
 WHERE e.deptno=d.deptno;

 观察查询结果 显示 只有3个部门被显示出来了 因为有一个部门(40部门)是没有员工的
 此时要使用外连接

 我们先测试(+)什么叫左右连接
 SELECT e.empno,e.ename,d.deptno,d.dname,d.loc
 FROM emp e, dept d
 WHERE e.deptno=d.deptno(+);
 观察结果可知以上+号写和不写是一样的,是因为左表员工表中每一个员工都是有部门的
 此时结果没有变化 还是14条记录

 我们再将+号放在左表测试:
 SELECT e.empno,e.ename,d.deptno,d.dname,d.loc
 FROM emp e, dept d
 WHERE e.deptno(+)=d.deptno;
 结果显示15条记录 没有雇员的40号部门也显示出来了
 可以得出如下结论:(+)在右边为左连接要遍历左表的所有记录
           (+)在左边为右连接要遍历右表的所有记录
 左右连接在一般的开发中使用较多,就像我们之前查询雇员和领导关联的时候使用的左右连接。
 
 4.3 SQL 1999语法对SQL的支持(了解)
 
 范例:交叉连接(CROSS JOIN):产生笛卡尔积
 SELECT * FROM emp CROSS JOIN dept; 查询结果为56条记录产生了笛卡尔积
 范例:自然连接(NATURAL JOIN) 自动进行关联字段的匹配
 SELECT * FROM emp NATURAL JOIN dept;
 范例: USING 子句 直接指定关联的操作列
 SELECT * FROM emp e JOIN dept d USING(deptno) WHERE deptno=30;
 范例: ON子句:用户自己编写的连接条件
 SELECT * FROM emp e JOIN dept d ON(e.deptno=d.deptno) WHERE d.deptno=30;
 范例:左连接(左外连接) 右连接(右外连接)
 SELECT e.ename,e.deptno,d.dname
 FROM emp e RIGHT OUTER JOIN dept d ON(e.deptno=d.deptno);

原创粉丝点击