一、问题描述
有时我们为了保留某个表中的数据,而该表中的数据在另外一个关联表中未必都存在对应,此时就应该试用外连接查询。
比如:两个表,产品表和子产品表
注:子产品的parent_product_id便是产品表的id
产品可以有子产品,也可以没有子产品
遇到类似的问题需要使用外连接查询,保证所有的产品被查询出来,而其对应的子产品也在查询结果中。
二、问题解决
1.基础概念
笛卡尔积:例如,A={a,b}, B={0,1,2},则
即,一个集合在左和在右做“笛卡尔积”结果是不同的。
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;
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中emp和dept表做示例
dept:
emp:
1.相同的左外连接查询得到不同的展示结果
select dept.deptno,dept.dname, emp.ename,emp.empno from dept left join emp on dept.deptno = emp.deptno;
select emp.ename,emp.empno, dept.deptno,dept.dname from dept left join emp on dept.deptno = emp.deptno;
结论:红色部分完全相同,说明外连接方向及条件一样,区别在查询的字段排序不同,导致结果不同。
而第二种结果不能代表此次查询是右外连接
2.on条件上等号左右字段颠倒,效果是否相同
select dept.deptno,dept.dname, emp.ename,emp.empno from dept left join emp on dept.deptno = emp.deptno;
select dept.deptno,dept.dname, emp.ename,emp.empno from dept left join emp on emp.deptno = dept.deptno;
结论:对比结果发现,没有任何区别
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表中的所有内容
+放置的位置:哪面少哪面用+号,或者说哪面可能出现空记录,哪面用+号