Oracle中left join,right join,inner join分析

    在開始分析之前,我們先準備一些測試數據。首先,初始化三張表,分別爲test_user,test_team,test_type,建表語句如下

create table TEST_USER
(
  user_id   NUMBER,
  user_name VARCHAR2(30 CHAR),
  user_team NUMBER,
  user_type VARCHAR2(30 CHAR)
);
create table test_team(
team_id number,
team_name varchar2(30char)
);
create table test_type(
type_id number,
type_name varchar2(30char)
);
初始化數據

insert into TEST_USER (USER_ID, USER_NAME, USER_TEAM, USER_TYPE)
values (1, 'user1', 1, '1');

insert into TEST_USER (USER_ID, USER_NAME, USER_TEAM, USER_TYPE)
values (2, 'user2', 2, null);

insert into TEST_USER (USER_ID, USER_NAME, USER_TEAM, USER_TYPE)
values (3, 'user3', 5, '2');

insert into TEST_USER (USER_ID, USER_NAME, USER_TEAM, USER_TYPE)
values (4, 'user4', null, '3');

insert into TEST_USER (USER_ID, USER_NAME, USER_TEAM, USER_TYPE)
values (5, 'user5', 3, '6');


insert into TEST_TEAM (TEAM_ID, TEAM_NAME)
values (1, 'team1');

insert into TEST_TEAM (TEAM_ID, TEAM_NAME)
values (2, 'team2');

insert into TEST_TEAM (TEAM_ID, TEAM_NAME)
values (3, 'team3');

insert into TEST_TEAM (TEAM_ID, TEAM_NAME)
values (4, 'team4');


insert into TEST_TYPE (TYPE_ID, TYPE_NAME)
values (1, 'type1');

insert into TEST_TYPE (TYPE_ID, TYPE_NAME)
values (2, 'type2');

insert into TEST_TYPE (TYPE_ID, TYPE_NAME)
values (3, 'type3');
三張表的數據,如下表格

表:test_user

USER_ID USER_NAME USER_TEAM USER_TYPE
1 user1 1 1
2 user2 2  
3 user3 5 2
4 user4   3
5 user5 3 6
表:test_team

TEAM_ID TEAM_NAME
1 team1
2 team2
3 team3
4 team4

表:test_type

TYPE_ID TYPE_NAME
1 type1
2 type2
3 type3

一、左連接  left join 

  左連接是把left join左邊表的數據都查詢出來,具體用法,比如

select * from test_user a left join test_team b on a.user_team=b.team_id
查詢結果如下

這裏left join語句中左側表,即test_user表所有記錄都會查詢出來,on關鍵字後面跟的關聯條件應理解爲匹配條件,對於left join右側的表,即test_team表滿足匹配條件的,顯示對應右側表的記錄信息,不滿足匹配條件右側表對應字段的記錄顯示爲NULL。

下面我們再來看一個sql

select * from test_user a left join test_team b on a.user_team=b.team_id and b.team_id=1
查詢結果如下


通過上述的描述可知,表test_user和test_team滿足a.user_team=b.team_id and b.team_id=1匹配條件的只有第一條記錄

其他不滿足匹配條件的test_team對應字段顯示爲NULL.

我們繼續查詢一個sql

select * from test_user a left join test_team b on a.user_team=b.team_id and a.user_id=2
查詢結果如下

同上,表test_user和test_team滿足a.user_team=b.team_id and a.user_id=2匹配條件的只有第一條記錄,其他不滿足匹配條件的test_team對應字段顯示爲NULL.

關於on條件與where的區別

我們將sql

select * from test_user a left join test_team b on a.user_team=b.team_id and b.team_id=1
中的and該爲where

select * from test_user a left join test_team b on a.user_team=b.team_id where b.team_id=1
查詢結果如下


這裏的where應理解過濾條件,查詢是會先按on後的匹配條件a.user_team=b.team_id形成符合要求的臨時表,然後where後面的條件b.team_id=1剔除不符合條件的記錄。

同理,另一個改寫的sql

select * from test_user a left join test_team b on a.user_team=b.team_id where a.user_id=2
查詢結果如下


oracle中的(+)

 在oracle中左連接left join可以用左連接的表,在其關聯關係一側加(+)表示,

比如左連接sql

select * from test_user a left join test_team b on a.user_team=b.team_id
改寫成(+)形式,有如下兩種方式,效果是一樣的

select * from test_user a,test_team b where  a.user_team=b.team_id(+);
或者

select * from test_user a,test_team b where b.team_id(+)=a.user_team;
oracle中left join和用(+)表達的方式在執行上性能是一樣的。對應的執行計劃分別如下:




這裏還有個值得注意的地方,如若sql 

select * from test_user a left join test_team b on a.user_team=b.team_id and b.team_id=1

改寫成(+)該如何改寫呢?

這樣嗎?


這樣改寫是錯的,從查詢結果就可以看出來。因爲where後跟的是過濾條件,在

select * from test_user a left join test_team b on a.user_team=b.team_id and b.team_id=1

中b.team_id=1在on後面作爲匹配條件,不影響結果返回的條數,不會根據條件對結果進行剔除。這裏將b.team_id=1放在where是過濾條件。

正確的改寫方式,應按照上面的強調的 左連接left join可以用左連接的表,在其關聯關係一側加(+)表示(其實右連接right join也一樣),即改寫如下

select * from test_user a,test_team b where a.user_team=b.team_id(+) and b.team_id(+)=1;
查詢結果如下



二、右連接 right join

右連接是把right join左邊表的數據都查詢出來,具體用法,比如

select * from test_type a right join test_user b on a.type_id=b.user_type
查詢結果如下


這裏right join語句中右側表,即test_user表所有記錄都會查詢出來,on關鍵字後面跟的關聯條件應理解爲匹配條件,對於right join左側的表,即test_type表滿足匹配條件的,顯

示對應右側表的記錄信息,不滿足匹配條件左側表對應字段的記錄顯示爲NULL。

對於right join可以類比left join來看,包括在oracle用(+)來進行改寫,只不過(+)要加在right join左側表在關聯關係中的一側。

三、內連接inner join

如果說right join,left join是拿一張表去匹配另一張表,匹配上信息對應信息,否則返回NULL,而內連接呢相當於兩張表相互匹配,取其交集。即相當於where後的=連接。

所以下方兩個sql是等效的。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章