not in、not exists 及用join改寫
/*我們接著用上次建的兩個表。資料如下*/
SQL> select * from l;
STR V
------ -
left_1 1
left_2 2
left_3 3
left_4 4
SQL> select * from r;
STR V
------- -
right_3 3
right_4 4
right_5 5
right_6 6
/*如果要返回l表中有而r表為沒有的資料(v=1、2),那麼用not in寫應該如下*/
SQL> select * from l where v not in(select r.v from r);
STR V
------ -
left_1 1
left_2 2
/*如果r表中v有空值呢*/
SQL> insert into r values(null,null);
1 row inserted
/*結果集返回錯誤*/
SQL> select * from l where v not in(select r.v from r);
STR V
------ -
/*這時要增加條件 r.v is not null*/
SQL> select * from l where v not in(select r.v from r where r.v is not null);
STR V
------ -
left_1 1
left_2 2
/*not exists語句不受null影響,因為not exists中是等值關係*/
SQL> select * from l where not exists(selectnull from r where r.v = l.v);
STR V
------ -
left_1 1
left_2 2
/*以上兩種都叫反聯接,也可以用join改寫解析如下*/
SQL> select l.*,r.* from l left join ron l.v = r.v order by 2;
STR V STR V
------ - ------- -
left_1 1
left_2 2
left_3 3 right_3 3
left_4 4 right_4 4
/*如上所示,l中有,而r中沒有的,就是r.v為空的行,那麼加上這個條件後,返回的就是所需資料了*/
SQL> select l.* from l left join r onl.v = r.v where r.v is null order by 2;
STR V
------ -
left_1 1
left_2 2
/*如果能前的(+)寫法,應該如下,為了便於理解,我們仍分步執行來看*/
SQL> select left_str,left_v from (selectl.str as left_str,l.v as left_v,r.str as right_str,r.v as right_v from l,rwhere l.v = r.v(+) order by 2);
LEFT_STR LEFT_V
-------- ------
left_1 1
left_2 2
left_3 3
left_4 4
SQL> select left_str,left_v from (selectl.str as left_str,l.v as left_v,r.str as right_str,r.v as right_v from l,rwhere l.v = r.v(+)) where right_v is null orderby 2;
LEFT_STR LEFT_V
-------- ------
left_1 1
left_2 2
/*簡化後,語句如下*/
SQL> select l.* from l,r where l.v =r.v(+) and r.v is null order by 2;
STR V
------ -
left_1 1
left_2 2
/*有人把這兩種弄混了,寫為*/
select l.* from l left join r on (l.v =r.v) and r.v is null order by 2;
/*那麼我們把兩個表的資料都返回,看結果*/
SQL> select l.*,r.* from l left join ron (l.v = r.v) and r.v is null order by 2;
STR V STR V
------ - ------- -
left_1 1
left_2 2
left_3 3
left_4 4
/*以上這句整理一下就是*/
SQL> select l.*,r.* from l left join(select * from r where r.v is null)r on (l.v =r.v) order by 2;
STR V STR V
------ - ------- -
left_1 1
left_2 2
left_3 3
left_4 4
/*相當於是l與一空行join了*/
SQL> select * from r where r.v is null;
STR V
------- -
SQL>
/*對join的方法引申一部,改為full join*/
SQL> select l.*,r.* from l full join ron l.v = r.v order by 2,4;
STR V STR V
------ - ------- -
left_1 1
left_2 2
left_3 3 right_3 3
left_4 4 right_4 4
right_5 5
right_6 6
7 rows selected
SQL>
/*看上述結果,對別對應l.v為空,與r.v為空就是兩個表不匹配的行*/
SQL> select l.*,r.* from l full join ron l.v = r.v where (l.v is null or r.v is null)order by 2,4;
STR V STR V
------ - ------- -
left_1 1
left_2 2
right_5 5
right_6 6
SQL>
/*當然,以上語句就不能用(+)改寫了*/