1. 程式人生 > >not in、not exists 及用join改寫

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=12),那麼用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>

/*當然,以上語句就不能用(+)改寫了*/