09-Oracle入门之多表查询

笛卡尔集

  • 笛卡尔集会在下面条件下产生:
    • 省略连接条件
    • 连接条件无效
    • 所有表中的所有行互相连接
  • 为了避免笛卡尔集, 可以在 WHERE 加入有效的连接条件。
  • 在实际运行环境下,应避免使用全笛卡尔集。

列相加,行相乘

SQL> ed
        已写入 file afiedt.buf

          1  select count(*)
          2* from dept, emp
        SQL> /

          COUNT(*)
        ----------
                56

通过连接条件可以避免笛卡尔积

1  select *
2  from dept d, emp e
3* where e.deptno = d.deptno
SQL> /

连接的类型

这里写图片描述

使用连接在多个表中查询数据的一般套路:

SELECT  table1.column, table2.column
FROM    table1, table2
WHERE   table1.column1 = table2.column2;
  • 在 WHERE 子句中写入连接条件。
  • 在表中有相同列时,在列名之前加上表名前缀

等值连接

这里写图片描述

一般套路

SELECT employees.employee_id, employees.last_name, 
       employees.department_id, departments.department_id,
       departments.location_id
FROM   employees, departments
WHERE  employees.department_id = departments.department_id;

这里写图片描述

多个连接条件与 AND 操作符

这里写图片描述

区分重复的列名

  • 使用表名前缀在多个表中区分相同的列。
  • 在不同表中具有相同列名的列可以用表的别名加以区分。

表的别名

  • 使用别名可以简化查询。
  • 使用表名前缀可以提高执行效率
  • 如果使用了表的别名,则不能再使用表的真名。
SELECT e.employee_id, e.last_name, e.department_id,
       d.department_id, d.location_id
FROM   employees e , departments d
WHERE  e.department_id = d.department_id;

连接多个表

这里写图片描述

非等值连接

这里写图片描述

SELECT e.last_name, e.salary, j.grade_level
FROM   employees e, job_grades j
WHERE  e.salary 
       BETWEEN j.lowest_sal AND j.highest_sal;

这里写图片描述

查询员工信息,员工号,姓名,月薪, 薪水级别

SQL> ed
Wrote file afiedt.buf

  1  select  e.empno, e.ename, e.sal, s.grade
  2  from emp e, SALGRADE s
  3* where e.sal >= s.losal and e.sal <=s.hisal
  4  /

     EMPNO ENAME         SAL      GRADE
---------- ---------- ---------- ----------
      7369 SMITH         800      1
      7900 JAMES         950      1
      7876 ADAMS        1100      1
      7521 WARD         1250      2
      7654 MARTIN       1250      2
      7934 MILLER       1300      2
      7844 TURNER       1500      3
      7499 ALLEN        1600      3
      7782 CLARK        2450      4
      7698 BLAKE        2850      4
      7566 JONES        2975      4
      7902 FORD         3000      4
      7788 SCOTT        3000      4
      7839 KING         5000      5
     1 tom_abc      8000      5

15 rows selected.

外连接

这里写图片描述

  • 使用外连接可以查询不满足连接条件的数据。
  • 外连接的符号是 (+)。
SELECT  table1.column, table2.column
FROM    table1, table2
WHERE   table1.column(+) = table2.column;
SELECT  table1.column, table2.column
FROM    table1, table2
WHERE   table1.column = table2.column(+);
SELECT e.last_name, e.department_id, d.department_name
FROM   employees e, departments d
WHERE  e.department_id(+) = d.department_id ; 

这里写图片描述

按部门统计员工人数: 部门号 部门名称 各部门人数

  • 确定是多表查询,因为 部门表中没有人数,人数和员工表有关
  • 因为 按照各个部门人数 ,所以用到分组查询

  • 第一阶段的写法

SQL> ed
Wrote file afiedt.buf

  1  select d.deptno, d.dname, count(*)
  2     from dept d, emp e
  3     where d.deptno = e.deptno
  4*    group by d.deptno, d.dname
SQL> /

    DEPTNO DNAME        COUNT(*)
---------- -------------- ----------
    10 ACCOUNTING          4
    20 RESEARCH        5
    30 SALES           6

40号部门为什么没有被统计
希望 把不符合条件的部门(40部门)也要显示出来:

SQL> ed
Wrote file afiedt.buf

  1  select d.deptno, d.dname, count(e.empno)
  2     from dept d, emp e
  3     where d.deptno = e.deptno(+)
  4*    group by d.deptno, d.dname
SQL> /

    DEPTNO DNAME      COUNT(E.EMPNO)
---------- -------------- --------------
    10 ACCOUNTING              4
    40 OPERATIONS              0
    20 RESEARCH            5
    30 SALES               6

对于这类希望把不满足等值条件(这里是where d.deptno = e.deptno)的数据,也显示出来,需要用到外链接。

  • 左连接: 想把 d.deptno都显示出来,,把(+)写在等号的右边 ,叫左连接
  • 左连接: 想把 d.deptno都显示出来,,把(+)写在等号的左边 ,叫右连接

自连接

这里写图片描述

SELECT worker.last_name || ' works for ' 
       || manager.last_name
FROM   employees worker, employees manager
WHERE  worker.manager_id = manager.employee_id ;

这里写图片描述

查询员工信息 ,老板信息,显示: xxx的老板是xxx

等值连接条件 :员工表的老板= 老板表的员工

不能显示大老板:

select e.ename || '的老板是'|| b.ename
            from emp e, emp b
            where e.mgr = b.empno

显示大老板:

select e.ename || '的老板是'|| b.ename
            from emp e, emp b
            where e.mgr = b.empno(+)

优化显示:

QL> ed
Wrote file afiedt.buf

  1  select e.ename || '  works for  '|| nvl(b.ename, 'himself')
  2             from emp e, emp b
  3*            where e.mgr = b.empno(+)
SQL> /

E.ENAME||'WORKSFOR'||NVL(B.ENAME,
---------------------------------
FORD  works for  JONES
SCOTT  works for  JONES
JAMES  works for  BLAKE
TURNER  works for  BLAKE
MARTIN  works for  BLAKE
WARD  works for  BLAKE
ALLEN  works for  BLAKE
MILLER  works for  CLARK
ADAMS  works for  SCOTT
CLARK  works for  KING
BLAKE  works for  KING
JONES  works for  KING
SMITH  works for  FORD
KING  works for  himself
tom_abc  works for  himself

15 rows selected.

使用SQL: 1999 语法连接

使用连接从多个表中查询数据

SELECT  table1.column, table2.column
FROM    table1
[CROSS JOIN table2] |
[NATURAL JOIN table2] |
[JOIN table2 USING (column_name)] |
[JOIN table2 
  ON(table1.column_name = table2.column_name)] |
[LEFT|RIGHT|FULL OUTER JOIN table2 
  ON (table1.column_name = table2.column_name)];

叉集

  • 使用CROSS JOIN 子句使连接的表产生叉集。
  • 叉集和笛卡尔集是相同的。
SELECT last_name, department_name
FROM   employees
CROSS JOIN departments ;

这里写图片描述

自然连接

  • NATURAL JOIN 子句,会以两个表中具有相同名字的列为条件创建等值连接。
  • 在表中查询满足等值条件的数据。
  • 如果只是列名相同而数据类型不同,则会产生错误。
SELECT department_id, department_name,
       location_id, city
FROM   departments
NATURAL JOIN locations ;

这里写图片描述

使用 USING 子句创建连接

  • 在NATURAL JOIN 子句创建等值连接时,可以使用 USING 子句指定等值连接中需要用到的列。
  • 使用 USING 可以在有多个列满足条件时进行选择。
  • 不要给选中的列中加上表名前缀或别名。
  • NATURAL JOIN 和 USING 子句经常同时使用。

USING 子句

SELECT e.employee_id, e.last_name, d.location_id
FROM   employees e JOIN departments d
USING (department_id) ;

这里写图片描述

使用ON 子句创建连接

  • 自然连接中是以具有相同名字的列为连接条件的。
  • 可以使用 ON 子句指定额外的连接条件。
  • 这个连接条件是与其它条件分开的。
  • ON 子句使语句具有更高的易读性。
SELECT e.employee_id, e.last_name, e.department_id, 
       d.department_id, d.location_id
FROM   employees e JOIN departments d
ON     (e.department_id = d.department_id);

这里写图片描述

使用 ON 子句创建多表连接

SELECT employee_id, city, department_name
FROM   employees e 
JOIN   departments d
ON     d.department_id = e.department_id 
JOIN   locations l
ON     d.location_id = l.location_id;

这里写图片描述

内连接和外连接再深入

  • 在SQL: 1999中,内连接只返回满足连接条件的数据

  • 两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的行 ,这种连接称为左(或右) 外联接。

  • 两个表在连接过程中除了返回满足连接条件的行以外还返回两个表中不满足条件的行 ,这种连接称为满 外联接。

左外联接

SELECT e.last_name, e.department_id, d.department_name
FROM   employees e
LEFT OUTER JOIN departments d
ON   (e.department_id = d.department_id) ;

这里写图片描述

右外联接

SELECT e.last_name, e.department_id, d.department_name
FROM   employees e
RIGHT OUTER JOIN departments d
ON    (e.department_id = d.department_id) ;

这里写图片描述

满外联接

SELECT e.last_name, e.department_id, d.department_name
FROM   employees e
FULL OUTER JOIN departments d
ON   (e.department_id = d.department_id) ;

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值