兩種連線的表達 :left(right) join 和 (+)
稍微研究了一下 oracle 自己的join 和標準的join。主要表現在on ,where 關鍵字所起的作用不同,和連線本身的特性。
yang@ORACL> set autotrace on
yang@ORACL> select *
2 from a,b
3 where a.id=b.id(+) and a.name like 'x%';
ID NAME ID NAME
---------- ----- ---------- -----
1 x1 1 x1
2 x2 2 x2
4 x4
3 x3
執行計劃
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 280 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN OUTER | | 4 | 280 | 7 (15)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| A | 4 | 140 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| B | 2 | 70 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."ID"="B"."ID"(+))
2 - filter("A"."NAME" LIKE 'x%')
由執行計劃可以看出先對a表進行過濾,讓後進行與b表的left join,
--
yang@ORACL> select * from a left join b
2 on a.id=b.id and a.name like 'x%';
ID NAME ID NAME
---------- ----- ---------- -----
1 x1 1 x1
2 x2 2 x2
3 x3
4 x4
1 y1
2 y2
3 y3
4 y4
已選擇8行。
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8 | 560 | 27 (0)| 00:00:01 |
| 1 | NESTED LOOPS OUTER | | 8 | 560 | 27 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL | A | 8 | 280 | 3 (0)| 00:00:01 |
| 3 | VIEW | | 1 | 35 | 3 (0)| 00:00:01 |
|* 4 | FILTER | | | | | |
|* 5 | TABLE ACCESS FULL| B | 1 | 35 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - filter("A"."NAME" LIKE 'x%')
5 - filter("A"."ID"="B"."ID")
-- 先連線後篩選 (由 Table A 驅動 NESTED LOOPS OUTER ,每一次迴圈篩選記錄
外連線中的on不需要過濾基表資料,過濾基表資料是在where裡做的,on只是連線條件,根據連線條件找匹配的從表資料,找不到匹配的從錶行,則置空。
yang@ORACL> select * from a left join b
2 on a.id=b.id
3 where a.name like 'x%';
ID NAME ID NAME
---------- ----- ---------- -----
1 x1 1 x1
2 x2 2 x2
4 x4
3 x3
執行計劃
----------------------------------------------------------
Plan hash value: 1365417139
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 280 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN OUTER | | 4 | 280 | 7 (15)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| A | 4 | 140 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| B | 2 | 70 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."ID"="B"."ID"(+))
2 - filter("A"."NAME" LIKE 'x%')
Note
-----
- dynamic sampling used for this statement
yang@ORACL> select * from a left join b
2 on a.name like 'x%'
3 where a.id=b.id;
ID NAME ID NAME
---------- ----- ---------- -----
1 x1 1 x1
2 x2 2 x2
執行計劃
----------------------------------------------------------
Plan hash value: 652036164
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 70 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN | | 1 | 70 | 7 (15)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| A | 1 | 35 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| B | 2 | 70 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."ID"="B"."ID")
2 - filter("A"."NAME" LIKE 'x%')
需要說明的是:
on關鍵字,的確是連線條件,它不能過濾基表。過濾不了的原因是on過濾掉的emp表結果,最後又被left outer join拿了回來。
select e.ename,d.dname from emp e left outer join dept d on d.deptno=e.deptno and e.ename='SCOTT';
虛擬碼
for rec_e in ( select ename from emp e ) loop
for rec_d in ( select dname from dept d where d.deptno = rec_e.deptno ) loop
if rec_d != NULL and rec_e..ename='SCOTT' then
show (rec_e.ename,rec_d.name);
else
show (rec_e.ename,null); --on過濾掉的emp表結果,最後又被left outer join拿了回來。
end if;
end loop;
end loop;
--虛擬碼部分內容參考了puber ccsnmoracle 的表述
yang@ORACL> set autotrace on
yang@ORACL> select *
2 from a,b
3 where a.id=b.id(+) and a.name like 'x%';
ID NAME ID NAME
---------- ----- ---------- -----
1 x1 1 x1
2 x2 2 x2
4 x4
3 x3
執行計劃
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 280 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN OUTER | | 4 | 280 | 7 (15)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| A | 4 | 140 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| B | 2 | 70 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."ID"="B"."ID"(+))
2 - filter("A"."NAME" LIKE 'x%')
由執行計劃可以看出先對a表進行過濾,讓後進行與b表的left join,
--
yang@ORACL> select * from a left join b
2 on a.id=b.id and a.name like 'x%';
ID NAME ID NAME
---------- ----- ---------- -----
1 x1 1 x1
2 x2 2 x2
3 x3
4 x4
1 y1
2 y2
3 y3
4 y4
已選擇8行。
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8 | 560 | 27 (0)| 00:00:01 |
| 1 | NESTED LOOPS OUTER | | 8 | 560 | 27 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL | A | 8 | 280 | 3 (0)| 00:00:01 |
| 3 | VIEW | | 1 | 35 | 3 (0)| 00:00:01 |
|* 4 | FILTER | | | | | |
|* 5 | TABLE ACCESS FULL| B | 1 | 35 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - filter("A"."NAME" LIKE 'x%')
5 - filter("A"."ID"="B"."ID")
-- 先連線後篩選 (由 Table A 驅動 NESTED LOOPS OUTER ,每一次迴圈篩選記錄
外連線中的on不需要過濾基表資料,過濾基表資料是在where裡做的,on只是連線條件,根據連線條件找匹配的從表資料,找不到匹配的從錶行,則置空。
yang@ORACL> select * from a left join b
2 on a.id=b.id
3 where a.name like 'x%';
ID NAME ID NAME
---------- ----- ---------- -----
1 x1 1 x1
2 x2 2 x2
4 x4
3 x3
執行計劃
----------------------------------------------------------
Plan hash value: 1365417139
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 280 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN OUTER | | 4 | 280 | 7 (15)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| A | 4 | 140 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| B | 2 | 70 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."ID"="B"."ID"(+))
2 - filter("A"."NAME" LIKE 'x%')
Note
-----
- dynamic sampling used for this statement
yang@ORACL> select * from a left join b
2 on a.name like 'x%'
3 where a.id=b.id;
ID NAME ID NAME
---------- ----- ---------- -----
1 x1 1 x1
2 x2 2 x2
執行計劃
----------------------------------------------------------
Plan hash value: 652036164
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 70 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN | | 1 | 70 | 7 (15)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| A | 1 | 35 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| B | 2 | 70 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."ID"="B"."ID")
2 - filter("A"."NAME" LIKE 'x%')
需要說明的是:
on關鍵字,的確是連線條件,它不能過濾基表。過濾不了的原因是on過濾掉的emp表結果,最後又被left outer join拿了回來。
select e.ename,d.dname from emp e left outer join dept d on d.deptno=e.deptno and e.ename='SCOTT';
虛擬碼
for rec_e in ( select ename from emp e ) loop
for rec_d in ( select dname from dept d where d.deptno = rec_e.deptno ) loop
if rec_d != NULL and rec_e..ename='SCOTT' then
show (rec_e.ename,rec_d.name);
else
show (rec_e.ename,null); --on過濾掉的emp表結果,最後又被left outer join拿了回來。
end if;
end loop;
end loop;
--虛擬碼部分內容參考了puber ccsnmoracle 的表述
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30496894/viewspace-2039995/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 連線查詢簡析 join 、 left join 、 right join
- mysql常用連線查詢join,left,right,crossMySqlROS
- LEFT JOIN 和JOIN 多表連線
- sql left join 和 right join解釋SQL
- sql中的join、left join、right joinSQL
- MySQL LEFT JOIN/ INNER JOIN/RIGHT JOINMySql
- SQL中聯表查詢操作(LEFT JOIN, RIGHT JOIN, INNER JOIN)SQL
- Oracle Left join right jionOracle
- left join,right join,inner join的條件on和where的區別
- MySql的join(連線)查詢 (三表 left join 寫法)MySql
- sql之left join、right join、inner join的區別SQL
- sql的left join 、right join 、inner join之間的區別SQL
- oracle的left join,right join和full join的一點介紹(R1)Oracle
- sql 連線查詢例項(left join)三表連線查詢SQL
- oracle知識整理(1) union和union all的區別,left join和right join的區別(各種join的區別)Oracle
- 用實驗方法加深理解Oracle的外連線(left/right/full)和內連線(inner)Oracle
- 【SQL】13 SQL 別名、SQL 連線(JOIN)、SQL INNER JOIN 關鍵字、SQL LEFT JOIN 關鍵字、SQL RIGHT JOIN 關鍵字、SQL FULL OUTER JSQL
- 表連線 join和(+)、union和uion allUI
- Inner Join, Left Outer Join和Association的區別
- [20170203]12c left right 外連線的增強
- Oracle優化案例-用left join代替反連線 not in not exists(十)Oracle優化
- clear:left/right 理解
- sql語句左連結left join--3張表關聯SQL
- mysql + left joinMySql
- Oracle表連線操作——Hash Join(雜湊連線)下Oracle
- Oracle表連線操作——Hash Join(雜湊連線)上Oracle
- MySQL筆記-左連線的使用(left join有關聯的多表查詢)MySql筆記
- mysql left join轉inner joinMySql
- 表的連線方式:NESTED LOOP、HASH JOIN、SORT MERGE JOIN(轉)OOP
- Oracle中left join中右表的限制條件Oracle
- 兩表連線三:合併連線
- SQL語句中不同的連線JOIN及SQL中join的各種用法SQL
- HTTP代理的兩種連線方式HTTP
- mysql的left join和inner join的效率對比,以及如何優化MySql優化
- 三表關聯查詢-多次LEFT JOIN...ON
- Oracle表連線操作——Merge Sort Join(合併排序連線)Oracle排序
- 多表連線的三種方式詳解 hash join、merge join、 nested loopOOP
- Oracle(+)連線與Join連線Oracle