Oracle的left outer join查询(转)
来源:互联网 发布:电脑聊天交友软件 编辑:程序博客网 时间:2024/06/05 02:41
在偶然一次执行Oracle 9i的left outer join查询时,发现了一些匪夷所思的问题,在此贴出来和大家讨论一下。
先创建一些表和记录来模拟当时的情况:
create table temp_test1
(
a number(10)
);
INSERT INTO temp_test1 VALUES(1);
INSERT INTO temp_test1 VALUES(2);
INSERT INTO temp_test1 VALUES(3);
INSERT INTO temp_test1 VALUES(4);
COMMIT;
create table temp_test2
(
b number(10),
c varchar2(2)
);
INSERT INTO temp_test2 VALUES(1, 'a');
INSERT INTO temp_test2 VALUES(2, 'a');
INSERT INTO temp_test2 VALUES(3, 'a');
INSERT INTO temp_test2 VALUES(5, 'b');
COMMIT;
好了,我们来执行一个左外连接:
--最初想得到的结果
SELECT a, b, c
FROM temp_test1 LEFT OUTER JOIN temp_test2 ON temp_test1.a=temp_test2.b;
结果如下:
A B C
1 1 1 a
2 2 2 a
3 3 3 a
4 4
(预想的结果)
OK,在后面画蛇添足地加上个过滤条件:
--在temp_test2加一个条件(先连接,后过滤,结果少了一列)
SELECT a, b, c
FROM temp_test1 LEFT OUTER JOIN temp_test2 ON temp_test1.a=temp_test2.b
WHERE c='a';
结果居然少了一条:
A B C
1 1 1 a
2 2 2 a
3 3 3 a
(错误的结果)
从这个现象看,说明左外连接的时候,是先把两个表join起来,然后在合成后的结果集里面再做过滤。
再换种写法试试:
--在temp_test2加一个条件,换一种写法(似乎是过滤了再连接)
SELECT a, b, c
FROM temp_test1 LEFT OUTER JOIN temp_test2
ON temp_test1.a=temp_test2.b AND temp_test2.C='a';
神了,用这种方法居然是最初预想的结果。从这里看,似乎是在单表上过滤了再连接的。
不服气,把条件的顺序换了看:
SELECT a, b, c
FROM temp_test1 LEFT OUTER JOIN temp_test2
ON temp_test2.C='a' AND temp_test1.a=temp_test2.b;
还是我们预想的结果,看来条件的顺序和结果无关。
恩,越来越有趣了,再换写法,使用SQL89的连接语法:
--用另一种语法进行左连接
SELECT a,b,c
FROM temp_test1, temp_test2
WHERE temp_test1.a=temp_test2.b(+)
效果和left outer join果然是一样的!(废话)
加上画蛇添足的条件试试:
--用另一种语法进行左连接,加上过滤条件,发现是连接后再过滤
SELECT a,b,c
FROM temp_test1, temp_test2
WHERE temp_test1.a=temp_test2.b(+) AND temp_test2.C='a';
唉!错误的结果!再换条件的顺序:
--用另一种语法进行左连接,修改条件的顺序,发现还是连接后再过滤
SELECT a,b,c
FROM temp_test1, temp_test2
WHERE temp_test2.C='a' AND temp_test1.a=temp_test2.b(+);
还是错误的结果!
从上面的实验,我们得到了以下结论:
对于SQL92语法的左外连接(left outer join),WHERE的过滤条件是连接后再过滤的;
对于SQL92语法的左外连接(left outer join),把过滤条件写在FROM部分和写在WHERE部分效果是不同的;(为什么不同,到底有些什么不同不得而知,只能猜测)
对于SQL89语法的左外连接( =(+) ),都是连接后再过滤的。
经过测试,RIGHT OUTER JOIN的表现与LEFT OUTER JOIN是一致的。
对于LEFT OUTER JOIN如此怪异的行为,我推荐一种比较“安全”的写法,强制在语法中体现我们的意图:
--强制性地过滤后再连接
WITH
result1 AS
(
SELECT b, c FROM temp_test2 WHERE c='a'
)
SELECT a,b,c
FROM temp_test1 LEFT OUTER JOIN result1 ON temp_test1.a=result1.b;
- Oracle的left outer join查询(转)
- ORACLE- join,inner join 与 left join, left outer join
- join联接查询--SQL中 inner join、 left join 、right join、 outer join之间的区别
- 【Access】 LEFT OUTER JOIN 关联多表的查询语句
- left outer join 的真谛
- Oracle中Left Outer Join和外关联(+)的区别
- Oracle中Left Outer Join和外关联(+)的区别
- oracle中右表有过滤条件的left outer join
- left outer join,inner join,right outer join的区别
- left outer join 结合条件查询
- left outer join 改写标量子查询
- mysql中left join,right join,inner join,outer join的用法详解【转】
- SQL中 inner join、 left outer join 、right outer join、 full outer join之间的区别
- inner join,outer join,left join,right join的区别
- inner join,outer join,left join,right join的区别
- inner join,outer join,left join,right join的区别
- left join,right join,inner join,outer join的用法
- Inner join,outer join,left join,right join的区别
- SharedObject本地保存子swf
- PowerTip of the Day from powershell.com上周汇总(十)
- 快速上手的记录
- MFC中ASSERT()和VERIFY()区别
- 新建远程桌面 地方法
- Oracle的left outer join查询(转)
- Oracle UTL_FILE
- DELPHI中自适应表单的实现----转
- 如何选择Web报表工具
- linux脚本(shell)编程
- DW导出到excel文件(标题、数据)
- 人生如水
- 年轻人,这就是C语言家族的故事
- 模式匹配001: 基本概念