外連接(OUTER JOIN) , 交叉連接(CROSS JOIN),和三個操作符(UNION , INTERSECT , MINUS)
外連接(OUTER JOIN)
我們將建立兩個表,說明下面sql語句的使用原理
A表:
B表:
CREATE TABLE A( --A表
id NUMBER(2) ,
Aname VARCHAR2(5)
) ;
CREATE TABLE B( --B表
id NUMBER(2) ,
Bname VARCHAR2(5)
) ;
這兩個表中有一些id相同,有一些不同。
我們INSERT:
INSERT INTO a VALUES(1,'A01') ;
INSERT INTO a VALUES(6,'A06') ;
INSERT INTO a VALUES(7,'A07') ;
INSERT INTO a VALUES(8,'A08') ;
INSERT INTO a VALUES(12,'A12') ;
INSERT INTO a VALUES(13,'A13') ;
INSERT INTO a VALUES(14,'A14') ;
INSERT INTO B VALUES(2,'B02') ;
INSERT INTO B VALUES(3,'B03') ;
INSERT INTO B VALUES(4,'B04') ;
INSERT INTO B VALUES(5,'B05') ;
INSERT INTO B VALUES(6,'B06') ;
INSERT INTO B VALUES(7,'B07') ;
INSERT INTO B VALUES(8,'B08') ;
對於外連接,Oracle中可以使用(+)來表示,也可以使用LEFT,RIGHT和FULL OUTER JOIN實現多個表外連接外連接分爲3類
1,左外連接(LEFT OUTER JOIN或LEFT JOIN)
2,右外連接(RIGHT OUTER JOIN或RIGHT JOIN)
3,全外連接(FULL OUTER JOIN或FULL JOIN)
使用外連接,可以列出與連接條件相匹配的行,並且列出左表(左外連接時),右表(右外連接時)或兩個表(全外連接時),所有符合檢索條件的數據行
1,左外連接:
SQL> SELECT a.id , a.aname , b.id , b.bname
2 FROM a LEFT OUTER JOIN b
3 ON a.id = b.id ;
ID ANAME ID BNAME
---------- ----- ---------- -----
6 A06 6 B06
7 A07 7 B07
8 A08 8 B08
13 A13
12 A12
1 A01
14 A14
已選擇7行。
~注:從定義的A表B表看來,只有id=6,7,8時兩個表的ID纔會相同,而left outer join會把左表,也就是a表與條件不匹配的也輸出來。而對於INNER JOIN ,我們可以對比一下效果:
SQL> SELECT a.id , a.aname , b.id , b.bname
2 FROM a INNER JOIN b
3 ON a.id = b.id ;
ID ANAME ID BNAME
---------- ----- ---------- -----
6 A06 6 B06
7 A07 7 B07
8 A08 8 B08
實際上外連接也可以這樣來寫:
SQL> SELECT a.id , a.aname , b.id , b.bname
2 FROM a INNER JOIN b
3 ON a.id = b.id(+) ;
ID ANAME ID BNAME
---------- ----- ---------- -----
6 A06 6 B06
7 A07 7 B07
8 A08 8 B08
13 A13
12 A12
1 A01
14 A14
已選擇7行。
與前面效果一樣。注意:這裏的(+)要與連接的方向相反。
因此,我們可以把外連接看成是內連接加上左表(當外連接爲左時),右表(當外連接爲右時)沒匹配的數據。
2,右外連接(與左連接類似,只是方向變了)
3,全外連接
這個其實也只是左連接與右連接的綜合,比較好理解。
SQL> SELECT a.id , a.aname , b.id , b.bname
2 FROM a FULL OUTER JOIN b
3 ON a.id = b.id ;
ID ANAME ID BNAME
---------- ----- ---------- -----
2 B02
3 B03
4 B04
5 B05
6 A06 6 B06
7 A07 7 B07
8 A08 8 B08
13 A13
12 A12
1 A01
14 A14
已選擇11行。
~注:從上面我們可以看出,相同id的兩個表都同時在,而id不同的則輸出空的值。
交叉連接
除此之外,外連接還有CROSS JOIN,也就是交叉連接,所得到的結果將是這兩個表中各行數據的所有組合,即這個表所有數據行的笛卡爾積。
交叉連接與簡單連接非常相似,不同的是,使用交叉連接時,在FROM字句中多個表名之間使用的不是逗號,而是使用CROSS JOIN隔開,而且不需要用ON指定條件,但可以在WHERE中添加。
SQL> SELECT a.id , a.aname , b.id , b.bname
2 FROM a CROSS JOIN b
3 WHERE a.id = b.id ;
ID ANAME ID BNAME
---------- ----- ---------- -----
6 A06 6 B06
7 A07 7 B07
8 A08 8 B08
當沒有WHERE條件時,將返回:
~注:從上面看,我們發現,交叉連接與之前的簡單連接差不多,若沒有where語句限制,也會產生笛卡爾積。
UNION , INTERSECT , MINUS操作符
我們繼續拿SCOTT的emp表作爲例子:
選取empno>7800的員工信息作爲集合A,部門號爲10的員工信息作爲集合B
集合A:
SQL> SELECT empno , ename , sal ,deptno
2 FROM emp
3 WHERE empno > 7800 ;
EMPNO ENAME SAL DEPTNO
---------- ---------- ---------- ----------
7839 KING 5000 10
7844 TURNER 1500 30
7876 ADAMS 1100 20
7900 JAMES 950 30
7902 FORD 3000 20
7934 MILLER 1300 10
已選擇6行。
集合B:
SQL> SELECT empno , ename , sal ,deptno
2 FROM emp
3 WHERE deptno = 10 ;
EMPNO ENAME SAL DEPTNO
---------- ---------- ---------- ----------
7782 CLARK 2450 10
7839 KING 5000 10
7934 MILLER 1300 10
直接看我們知道empno=7839與7934時A和B是相同的
下面我們分類進行解釋與試驗:
SQL語言中的MINUS集合運算,表示獲得給定集合之間的差異,也就意味着所得到的結果集中,其中的元素僅存在於前一個集合中,而不存在於另一集合中
如圖所示:
SQL> SELECT empno , ename , sal ,deptno
2 FROM emp
3 WHERE empno > 7800
4 MINUS
5 SELECT empno , ename , sal ,deptno
6 FROM emp
7 WHERE deptno = 10 ;
EMPNO ENAME SAL DEPTNO
---------- ---------- ---------- ----------
7844 TURNER 1500 30
7876 ADAMS 1100 20
7900 JAMES 950 30
7902 FORD 3000 20
INTERSECT獲取公共行,也稱爲獲取結果集的交集
如圖所示:
SQL> SELECT empno , ename , sal ,deptno
2 FROM emp
3 WHERE empno > 7800
4 INTERSECT
5 SELECT empno , ename , sal ,deptno
6 FROM emp
7 WHERE deptno = 10 ;
EMPNO ENAME SAL DEPTNO
---------- ---------- ---------- ----------
7839 KING 5000 10
7934 MILLER 1300 10
UNION返回多個查詢返回的行組合起來:
SQL> SELECT empno , ename , sal ,deptno
2 FROM emp
3 WHERE empno > 7800
4 UNION
5 SELECT empno , ename , sal ,deptno
6 FROM emp
7 WHERE deptno = 10 ;
EMPNO ENAME SAL DEPTNO
---------- ---------- ---------- ----------
7782 CLARK 2450 10
7839 KING 5000 10
7844 TURNER 1500 30
7876 ADAMS 1100 20
7900 JAMES 950 30
7902 FORD 3000 20
7934 MILLER 1300 10
~注:從上面我們看出,這三個運算符,只是在兩個SELECT語句中直接插入UNION,MINUS,INTERSECT三個之一。學過集合論的人對這些都不難理解。我們把每次SELECT得到的結果看成是一個集合,那麼三面的SQL語句我們就可以把它看成是集合間的運算了。
~綜:綜合這兩篇博客所學到的東西,我看到了Oracle多表連接查詢有很多看上去非常複雜的東西,比如INNER JOIN,OUTER JOIN ,CROSS JOIN等等這些,而當我逐步弄清楚後,就會發現這些其實只是多表查詢的基礎的一些遷移,原理還是一樣,只要理解了多表查詢的思想,就可以很容易理解外連接,內連接這些東西了。但我覺得這也只是基礎。學會了很多SQL的東西,卻不一定可以寫出好的SQL語句,甚至有些SQL語句也寫不出。學習是個積累的過程,對於博大精深的Oralce更是,千萬不能讓一時的收穫矇蔽了自己,自己還需花更多的時間去學習。繼續加油!