oracle——外连接查询

时间:2021-05-15 18:43:24

一、问题描述

  有时我们为了保留某个表中的数据,而该表中的数据在另外一个关联表中未必都存在对应,此时就应该试用外连接查询。

  比如:两个表,产品表和子产品表

oracle——外连接查询

注:子产品的parent_product_id便是产品表的id

  产品可以有子产品,也可以没有子产品

  遇到类似的问题需要使用外连接查询,保证所有的产品被查询出来,而其对应的子产品也在查询结果中。

二、问题解决

  1.基础概念

    笛卡尔积:例如,A={a,b}, B={0,1,2},则

         A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}
         B×A={(0, a), (0, b), (1, a), (1, b), (2, a), (2, b)}

    即,一个集合在左和在右做“笛卡尔积”结果是不同的。

  2.外连接查询

    2.1左外连接查询

select *
from table_a a left join table_b b
on a.id = b.parent_id

这样的结果就是左边的表中的内容都会被保留,而右边表每条数据会对应左边表中对应的数据,结果中,右边表中的所有内容只出现一次(table_a和table_b是一对多关系,且table_b中记录只对应一个table_a中记录),而左边表中一条记录可能显示多次。

e.g.

select pp.product_id,pp.product_name,p.product_id,p.product_name
from edu_product pp--产品
left join sub_edu_product p--子产品
on pp.product_id = p.parent_product_id;

oracle——外连接查询

    2.2右外连接

select *
from table_a a right join table_b b
on a.id = b.parent_id

这样的结果就是右边的表中的内容都会被保留,而右边表每条数据会对应左边表中对应的数据,结果中,右边表中的所有内容只出现一次(table_a和table_b是一对多关系,且table_b中记录只对应一个table_a中记录),而左边表中一条记录可能显示多次。和左外连接的区别是,左表不会保留多出来的数据

e.g.

select pp.product_id,pp.product_name,p.product_id,p.product_name
from edu_product pp--产品
right join sub_edu_product p--子产品
on pp.product_id = p.parent_product_id;

oracle——外连接查询

三、补充

  试用外连接查询时有时会有一些疑问,总结在下面:

  试用oracle中emp和dept表做示例

dept:oracle——外连接查询

emp:oracle——外连接查询

1.相同的左外连接查询得到不同的展示结果

select dept.deptno,dept.dname,
emp.ename,emp.empno
from dept left join emp
on dept.deptno = emp.deptno;

oracle——外连接查询

select emp.ename,emp.empno,
dept.deptno,dept.dname
from dept left join emp
on dept.deptno = emp.deptno;

oracle——外连接查询

结论:红色部分完全相同,说明外连接方向及条件一样,区别在查询的字段排序不同,导致结果不同。

   而第二种结果不能代表此次查询是右外连接

2.on条件上等号左右字段颠倒,效果是否相同

select dept.deptno,dept.dname,
emp.ename,emp.empno
from dept left join emp
on dept.deptno = emp.deptno;

oracle——外连接查询

select dept.deptno,dept.dname,
emp.ename,emp.empno
from dept left join emp
on emp.deptno = dept.deptno;

oracle——外连接查询

结论:对比结果发现,没有任何区别

3.使用+号进行外连接查询

select *
from (select e.empno,e.ename,d.deptno,d.dname
from emp e,dept d
where e.deptno = d.deptno) s, emp_dept ed
where ed.empno(+) = s.empno;

  emp_dept表中存放了emp,dept连接查询的部分结果。所以,s表包含了ed表中的所有内容

  +放置的位置:哪面少哪面用+号,或者说哪面可能出现空记录,哪面用+号