DROP TABLE TEST1 PURGE;
DORP TABLE TEST2 PURGE;
-- 左表
CREATE TABLE LEFT_TAB AS
SELECT 'left_1' as name, '1' AS id FROM dual UNION ALL
SELECT 'left_2' as name, '2' AS id FROM dual UNION ALL
SELECT 'left_3' as name, '3' AS id FROM dual UNION ALL
SELECT 'left_4' as name, '4' AS id FROM dual;
-- 右表
CREATE TABLE RIGHT_TAB AS
SELECT 'right_3' as name, '3' AS id FROM dual UNION ALL
SELECT 'right_4' as name, '4' AS id FROM dual UNION ALL
SELECT 'right_5' as name, '5' AS id FROM dual UNION ALL
SELECT 'right_6' as name, '6' AS id FROM dual;
-- inner join 返回两个表中的交集,因此左表的1,2和右表的5,6没有显示
/* INNER JOIN = JOIN */
SQL> SELECT AS left_name, AS right_name FROM left_tab l INNER JOIN right_tab r ON = ;
LEFT_N RIGHT_N
------ -------
left_3 right_3
left_4 right_4
/* where 写法 */
SELECT AS left_name, AS right_name FROM left_tab l, right_tab r WHERE = ;
-- left join 左表返回的所有行,右表返回与左边匹配的行, 因此左表显示1,2,3,4,右表显示3,4
/* LEFT JOIN = LEFT OUTER JOIN */
SQL> SELECT AS left_name, AS right_name FROM left_tab l LEFT JOIN right_tab r ON = order by 1;
LEFT_N RIGHT_N
------ -------
left_1
left_2
left_3 right_3
left_4 right_4
/* where(+) 写法 */
SQL> SELECT AS left_name, AS right_name FROM left_tab l, right_tab r WHERE =(+) order by 1;
LEFT_N RIGHT_N
------ -------
left_1
left_2
left_3 right_3
left_4 right_4
/* 使用left join和right join的时候需要注意驱动表的选择 */
SQL> SELECT /*+ leading(r,l) */ AS left_name, AS right_name FROM left_tab l, right_tab r WHERE =(+) order by 1;
Execution Plan
----------------------------------------------------------
Plan hash value: 1232751584
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 92 | 8 (25)| 00:00:01 |
| 1 | SORT ORDER BY | | 4 | 92 | 8 (25)| 00:00:01 |
|* 2 | HASH JOIN OUTER | | 4 | 92 | 7 (15)| 00:00:01 |
| 3 | TABLE ACCESS FULL| LEFT_TAB | 4 | 44 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| RIGHT_TAB | 4 | 48 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------
-- full join(没有+写法) 显示两个表的所有数据,但只有匹配的数据显示在同一行
SQL> SELECT AS left_name, AS right_name FROM left_tab l FULL JOIN right_tab r ON = order by 1;
LEFT_N RIGHT_N
------ -------
left_1
left_2
left_3 right_3
left_4 right_4
right_6
right_5
6 rows selected.
-- 如果多表inner join,最终结果只返回一个表的数据
SQL> SELECT , FROM left_tab l,right_tab r WHERE =(+) order by 1;
Execution Plan
----------------------------------------------------------
Plan hash value: 1232751584
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 56 | 8 (25)| 00:00:01 |
| 1 | SORT ORDER BY | | 4 | 56 | 8 (25)| 00:00:01 |
|* 2 | HASH JOIN OUTER | | 4 | 56 | 7 (15)| 00:00:01 |
| 3 | TABLE ACCESS FULL| LEFT_TAB | 4 | 44 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| RIGHT_TAB | 4 | 12 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------
对于上面的语句可以使用 in或者exists改写
SQL> SELECT name,id FROM left_tab l WHERE id IN (SELECT id FROM right_tab r WHERE =) order by 1;
Execution Plan
----------------------------------------------------------
Plan hash value: 3358900048
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 56 | 8 (25)| 00:00:01 |
| 1 | SORT ORDER BY | | 4 | 56 | 8 (25)| 00:00:01 |
|* 2 | HASH JOIN SEMI | | 4 | 56 | 7 (15)| 00:00:01 |
| 3 | TABLE ACCESS FULL| LEFT_TAB | 4 | 44 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| RIGHT_TAB | 4 | 12 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"="ID")
SQL> SELECT name,id FROM left_tab l WHERE EXISTS (SELECT NULL FROM right_tab r WHERE =) order by 1;
Execution Plan
----------------------------------------------------------
Plan hash value: 3358900048
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 56 | 8 (25)| 00:00:01 |
| 1 | SORT ORDER BY | | 4 | 56 | 8 (25)| 00:00:01 |
|* 2 | HASH JOIN SEMI | | 4 | 56 | 7 (15)| 00:00:01 |
| 3 | TABLE ACCESS FULL| LEFT_TAB | 4 | 44 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| RIGHT_TAB | 4 | 12 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("R"."ID"="L"."ID")
-- 多表连接的过滤条件
/* 当过滤条件在join后和where前时可以先过滤在join */
SQL> SELECT AS left_name, AS right_name FROM left_tab l LEFT JOIN right_tab r ON = and =3 ORDER BY 1 ;
LEFT_N RIGHT_N
------ -------
left_1
left_2
left_3 right_3
left_4
/* 改写后 */
SQL> SELECT AS left_name, AS right_name FROM left_tab l LEFT JOIN (SELECT * FROM right_tab WHERE id=3) R ON = ORDER BY 1;
LEFT_N RIGHT_N
------ -------
left_1
left_2
left_3 right_3
left_4
/* 当过滤条件在join后和where里面,CBO将自动改写为INNER JOIN,从ID2可以看出*/
SQL> SELECT AS left_name, AS right_name FROM left_tab l LEFT JOIN right_tab r ON = WHERE =3 ORDER BY 1 ;
Execution Plan
----------------------------------------------------------
Plan hash value: 901870180
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 23 | 8 (25)| 00:00:01 |
| 1 | SORT ORDER BY | | 1 | 23 | 8 (25)| 00:00:01 |
|* 2 | HASH JOIN | | 1 | 23 | 7 (15)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| RIGHT_TAB | 1 | 12 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| LEFT_TAB | 4 | 44 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("L"."ID"="R"."ID")
3 - filter(TO_NUMBER("R"."ID")=3)
-- 因此可以将上面的改写为
SQL> SELECT AS left_name, AS right_name FROM left_tab l JOIN (SELECT * FROM right_tab WHERE id=3) r ON =;
Execution Plan
----------------------------------------------------------
Plan hash value: 3321337660
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 23 | 7 (15)| 00:00:01 |
|* 1 | HASH JOIN | | 1 | 23 | 7 (15)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| RIGHT_TAB | 1 | 12 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| LEFT_TAB | 4 | 44 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("L"."ID"="RIGHT_TAB"."ID")
2 - filter(TO_NUMBER("ID")=3)
















