免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 18509 | 回复: 3
打印 上一主题 下一主题

[数据库] Oracle表连接精解 [复制链接]

论坛徽章:
7
天蝎座
日期:2013-08-16 23:19:32丑牛
日期:2014-01-08 09:20:14寅虎
日期:2014-01-11 11:03:44午马
日期:2014-04-28 11:02:40天秤座
日期:2014-05-16 23:24:24摩羯座
日期:2014-07-20 10:46:04卯兔
日期:2014-08-08 15:21:41
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-08-17 23:01 |只看该作者 |倒序浏览
下面比较全面,深入讲解了oracle关于表的连接的方式

附件: oracle表连接.docx (35.69 KB, 下载次数: 116)


Oracle表连接
Oracle语法&SQL1999语法:
1.笛卡尔乘积(CROSS JOIN)
   第一张表的所有行会与第二张表的所有行进行连接,即n*m方式进行连接
   oracle语法:
   select count(*) from hr.employees a ,hr.departments b;
    2889行
   雇员表的107行记录与部门表的27行记录相乘积(107*27),得到2889条记录
   SQL1999语法:
  select count(*) from hr.employees a cross join hr.departments b
    2889行

2.等价连接
   select a.department_id, b.department_id, a.employee_id, b.department_name
  from hr.employees a, hr.departments b
where a.department_id = b.department_id
   and a.department_id = 90
a.DEPARTMENT_ID        b.DEPARTMENT_ID        EMPLOYEE_ID        DEPARTMENT_NAME
90        90        100        Executive
90        90        101        Executive
90        90        102        Executive

把在a表和b表,部门相同,且部门号为90的员工匹配出来。
SQL1999语法:
在sql1999语法中的natural jion连接中,与oracle语法中的等值连接是有区别的.
先举例说明:
natural jion连接的条件是:两表连接中的列名要有相同的、相同的列名的值要相同的、相同的列名的数据类型要相同的。

sql-1:
select a.employee_id, a.manager_id, a.department_id
  from hr.employees a
where a.employee_id in (114, 115, 116, 117, 118, 119)
雇员表雇员114,115,116,117,118,119的相关结果集如下:
EMPLOYEE_ID        MANAGER_ID        DEPARTMENT_ID
114                          100                   30
115                  114                   30
116                       114            30
117                          114                   30
118                  114                   30
119                          114                   30

sql-2:
等值连接:
select a.employee_id, a.manager_id, a.department_id
  from hr.employees a, hr.departments b
where a.department_id = b.department_id
   and a.department_id = 30
EMPLOYEE_ID        MANAGER_ID        DEPARTMENT_ID
114                             100          30
115                            114          30
116                             114          30
117                     114          30
118                             114          30
119                             114          30

sql-3:
netural join:
select employee_id, manager_id, department_id
  from hr.employees a natural
  join hr.departments b
where department_id = 30
EMPLOYEE_ID        MANAGER_ID        DEPARTMENT_ID
115                            114          30
116                             114          30
117                     114          30
118                             114          30
119                             114          30

大家注意看,在sql-1中,我列出了雇员114~119的一些情况,在sql-2中,进行的是等值连接,而在sql-3中,进行的是NATURAL JOIN连接.
sql-2与sql-3的结果集的区别在哪里?
sql-2的等值连接中有雇员114的记录,而sql-3的NATURAL JOIN连接中没有雇员114的记录,为什么?
natural jion连接的条件是:
(1) 两表连接的列名要有相同的
(2) 两表连接的列名的数据类型要相同的
(3) 两表连接的列名的值要相同的,原因就在这里。
原因就是雇员表中部门30的雇员114的manager_id的值是100,而部门表中30号部门中没有manager_id=100的记录,所以,不符合条件(3),故而netural join连接中没有匹配雇员为为114的记录了,然而,等值连接则没有这样的条件,故而能匹配雇员为114的记录。
  这就是NATURAL JOIN与等值连接的区别。
其实NATURAL JOIN自然连接是两表中的相同的列的自然连接,换句话说,就是不需要人工干预,比方说,A表与B表有3列名相同,那么oracle NATURAL JOIN自然连接就连接相同的三列,自然连接的这相同的三列的列值是AND的关系,三列的条件必须同时满足才匹配,如果其中一列值不匹配,那么该列的列值就被抛弃。如果进行人工干预,比方说,我只需要使用其中一列作为连接列,那么这就是不是自然连接了,可以是USING子句,oracle等价连接来完成。
再举例一个:
看一个需要人工干预的等值连接:
select b.department_id "b-manager_id",
       a.department_id "a-department_id",
       b.manager_id    "b-department_id",
       a.manager_id    "a-manager_id"
  from hr.employees a, hr.departments b
where a.department_id = b.department_id
   and a.department_id = 30
b-department_id        a-department_id        b-manager_id        a-manager_id
30        30        114        100
30        30        114        114
30        30        114        114
30        30        114        114
30        30        114        114
30        30        114        114
看上述表格的第一行,a表列department_id,manager_id与b表department_id
,manager_id两列相同,但是这里我使用人工控制的方式来进行连接,就是说我选择了其中一个相同列deparament_id来进行连接,只有两表department_id匹配,就返回记录,而不管manager_id匹配不匹配.
自然连接则不同,下面举例:
select department_id "b-department_id",
       department_id "a-department_id",
       manager_id    "b-manager_id",
       manager_id    "a-manager_id"
  from hr.employees a natural join  hr.departments b
   where department_id = 30
b-department_id        a-department_id        b-manager_id        a-manager_id
30        30        114        114
30        30        114        114
30        30        114        114
30        30        114        114
30        30        114        114
看上图,自然连接就是两表所有相同的列进行连接,其实看sql语句也看出来了,上面的sql并没有连接条件,这也表示了是用两表中所有的相同的列进行连接,这是自然连接的第一个点,再有就是,比较两张表格的结果集,有所不同,b-manager_id=114与a-manager_id=100的结果集不符合自然连接的要求,故而自然连接的结果集中并没有显示,因为必须满足b-manager_id= a-manager_id的要求,其实,上述自然连接的sql可以等价如下语句:
select b.department_id "b-department_id",
         a.department_id "a-department_id",
         b.manager_id    "b-manager_id",
         a.manager_id    "a-manager_id"
    from hr.employees a, hr.departments b
   where a.department_id = 30
     and a.department_id = b.department_id
     and a.manager_id = b.manager_id
b-department_id        a-department_id        b-manager_id        a-manager_id
30        30        114        114
30        30        114        114
30        30        114        114
30        30        114        114
30        30        114        114
注意的是,自然连接的select 列表中,不允许有别名来限定表名,where 条件中也不允许有别名来限定表名。
上面讲的是两表连接。
自然连接中的多表(2张表以上)连接也是一样的。
select department_id "b-department_id",
       department_id "a-department_id",
       manager_id    "b-manager_id",
       manager_id    "a-manager_id",
       job_id   "c-job_id"
  from hr.employees a natural join  hr.departments b natural join hr.jobs c
   where department_id = 30
b-department_id        a-department_id        b-manager_id        a-manager_id        c-job_id
30        30        114        114        PU_CLERK
30        30        114        114        PU_CLERK
30        30        114        114        PU_CLERK
30        30        114        114        PU_CLERK
30        30        114        114        PU_CLERK

论坛徽章:
7
天蝎座
日期:2013-08-16 23:19:32丑牛
日期:2014-01-08 09:20:14寅虎
日期:2014-01-11 11:03:44午马
日期:2014-04-28 11:02:40天秤座
日期:2014-05-16 23:24:24摩羯座
日期:2014-07-20 10:46:04卯兔
日期:2014-08-08 15:21:41
2 [报告]
发表于 2013-08-17 23:02 |只看该作者
3.外连接
    Oracle语法:
   3.1 左外连接
select a.employee_id, a.department_id, b.department_id, b.department_name
  from hr.employees a, hr.departments b
where a.department_id = b.department_id(+)
   and a.employee_id in (100, 101, 17
order by a.employee_id
EMPLOYEE_ID        DEPARTMENT_ID        DEPARTMENT_ID        DEPARTMENT_NAME
100        90        90        Executive
101        90        90        Executive
178                                 空值        空值        空值
雇员178号没有部门号,这个如果连接条件是a.department_id = b.department_id,则不会匹配出雇员178,因为雇员表没有雇员178的的部门号,部门表也没有雇员178的部门号,空值与空值的匹配仍然是空值.但是如果是部门表b.department_id(+)这样与雇员表a.department_id进行连接,那么就会把雇员178给匹配出来.这就是oracle的左外连接.
    SQL1999语法:
select a.employee_id, a.department_id, b.department_id, b.department_name
  from hr.employees a left outer join hr.departments b
    on a.department_id = b.department_id
where a.employee_id in (100, 101, 17
order by a.employee_id
得出一样的结果集
  3.2 右外连接
select a.employee_id, a.department_id, b.department_id, b.department_name
  from hr.employees a, hr.departments b
where a.department_id(+) = b.department_id
and b.department_id in (110,120)
EMPLOYEE_ID        DEPARTMENT_ID        DEPARTMENT_ID        DEPARTMENT_NAME
205        110        110        Accounting
206        110        110        Accounting
空值        空值        120        Treasury
部门号120没有雇员,如果这个连接条件为a.department_id = b.department_id,将不会匹配部门号120的记录,因为雇员表的没有部门为120的部门,为空值,部门表有120号部门,空值与部门120进行匹配,得到的结果仍然是空值。但是如果雇员表想知道部门表里面还有哪些部门是没有雇员的,怎么办?那么这样可以解决这个问题,雇员表department_id(+)与部门表department_id进行连接,则可以将部门表没有雇员的部门也匹配出来。这就是Oracle的右外连接.
SQL1999语法:
select a.employee_id, a.department_id, b.department_id, b.department_name
  from hr.employees a right outer join hr.departments b
  on a.department_id = b.department_id
where b.department_id in (110,120)
得出一样的结果集
  3.2 全外连接
     oracle语法中并没有全外连接的写法,在sql1999语法中,有这个写法:
     使用 full outer join关键字来连接
      (略)

4.自连接
oracle语法中的自连接,是在一张表中进行连接,雇员表中的员工与管理员的关系,可以在一张雇员表中找出来,比如员工的管理者是谁。
举例:
比如90号部门的雇员情况如下:
select w.employee_id,
        w.first_name,
        w.last_name,
        w.manager_id,
        w.department_id
   from hr.employees w
  where w.department_id = 90
EMPLOYEE_ID        FIRST_NAME        LAST_NAME        MANAGER_ID        DEPARTMENT_ID
100        Steven        King                90
101        Neena        Kochhar        100        90
102        Lex        De Haan        100        90
员工101,102的的管理者为100,即Steven King.如果通过两张表的连接体现在一行上面.使用oracle的自连接可以实现这一点.
select w.employee_id as "员工编号",
        w.first_name || ' '||
        w.last_name as "员工姓名",
        m.employee_id as "管理者编号",
        m.first_name ||' ' ||
        m.last_name as "部门管理者",
        m.manager_id as  "部门管理者编号"
   from hr.employees w, hr.employees m
  where w.manager_id = m.employee_id
    and w.department_id = 90
员工编号        员工姓名        管理者编号        部门管理者        部门管理者编号
101        Neena Kochhar        100        Steven       
102        Lex De Haan        100        Steven       
使用自连接,实现了一行记录即有员工,也有管理者的记录,其实就是把雇员ID为100的一行记录分别与雇员ID为101,102的两行记录进行了合并而已。
这就是oracle的自连接。

5.using子句进行表连接
sql1999语法:
其实using 子句是相对于natural join来说的,其实就是等值连接
举例:
select department_id "b-department_id",
       department_id "a-department_id",
       manager_id    "b-manager_id",
       manager_id    "a-manager_id"
  from hr.employees a  join  hr.departments b using (department_id)
   where department_id = 30
b-department_id        a-department_id        b-manager_id        a-manager_id
30        30        114        100
30        30        114        114
30        30        114        114
30        30        114        114
30        30        114        114
30        30        114        114
相当于等值连接
注意的是,select 列表中,不允许有别名来限定表名,where 条件中也不允许有别名来限定表名。
也可以这样写:
select department_id "b-department_id",
       department_id "a-department_id",
       manager_id    "b-manager_id",
       manager_id    "a-manager_id"
  from hr.employees a  join  hr.departments b using (department_id,manager_id)
   where department_id = 30
b-department_id        a-department_id        b-manager_id        a-manager_id
30        30        114        114
30        30        114        114
30        30        114        114
30        30        114        114
30        30        114        114
相等于自然连接。
注意的是,select 列表中,不允许有别名来限定表名,where 条件中也不允许有别名来限定表名。
6.on子句

sql1999语法:
其实on子句只不过是等值连接另外一种写法罢了。
举例说明:
select b.department_id "b-department_id",
       a.department_id "a-department_id",
       b.manager_id    "b-manager_id",
       a.manager_id    "a-manager_id"
  from hr.employees a
  join hr.departments b
    on (a.department_id = b.department_id)
where a.department_id = 30
相当于:
select b.department_id "b-department_id",
       a.department_id "a-department_id",
       b.manager_id    "b-manager_id",
       a.manager_id    "a-manager_id"
  from hr.employees a, hr.departments b
where a.department_id = 30
   and b.department_id = a.department_id
得到相同的结果集:
b-department_id        a-department_id        b-manager_id        a-manager_id
30        30        114        100
30        30        114        114
30        30        114        114
30        30        114        114
30        30        114        114
30        30        114        114
注意的是,在on子句中,select 列表中,允许有别名来限定表名,where 条件中允许有别名来限定表名。

end.

论坛徽章:
0
3 [报告]
发表于 2014-02-18 10:54 |只看该作者
你好,看到你的帖子,受益很多,能否加QQ一起讨论下啊?我的QQ 2497321200

论坛徽章:
0
4 [报告]
发表于 2014-04-16 10:31 |只看该作者
太拽了。。。。。。。。。。。。。。。。。。。。。。。

   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP