PDF下載地址:SQL-內連接與外連接.pdf
連接查詢在關系型數據庫中經常用到,是多表聯合查詢的基礎。
主要包含:內連接,外連接,交叉連接。

內連接
內連接又分為等值連接,不等值連接,自然連接。
連接查詢中使用的比較運算符有:=, >, <, <>, >=, <=, !>, !<
等值連接
等值連接使用”=”來進行比較運算。
請看下面的例子:
| student_id | student_name | class_id |
|---|---|---|
| 1 | aaa | 15 |
| 2 | bbb | 16 |
| 3 | ccc | 17 |
| class_id | class_name |
|---|---|
| 15 | 五班 |
| 16 | 六班 |
| 17 | 七班 |
| 18 | 八班 |
如果需要查出一下內容:
每個學生所對應的班級名稱
此時就可用以下sql語句:
SELECT * FROM
T_student ts,T_class tc
WHERE
ts.class_id=tc.class_id
或者:
SELECT * FROM
T_student ts inner join T_class tc
ON
ts.class_id = tc.class_id
查詢結果如下:
| student_id | student_name | class_id | class_id | class_name |
|---|---|---|---|---|
| 1 | aaa | 15 | 15 | 五班 |
| 2 | bbb | 16 | 16 | 六班 |
| 3 | ccc | 17 | 17 | 七班 |
結論如下:
等值連接:
若要連接表t1和t2,比較條件為t1.a=t2.a,那么數據庫會用t1中a列的所有元素逐個和t2中的a進行比較,如果相等,則輸出該行。
至於數據庫內部如何實現,我們暫且不去深究。
不等值連接
內連接中,不使用”=”作為比較運算符,就叫不等值連接。
如果需要查詢以下內容:
T_student表和T_class表中,class_id字段不相等的所有組合
此時就可用以下sql語句:
SELECT * FROM
T_student ts,T_class tc
WHERE
ts.class_id <> tc.class_id
或者:
SELECT * FROM
T_student ts inner join T_class tc
ON
ts.class_id <> tc.class_id
查詢結果如下:
| student_id | student_name | class_id | class_id | class_name |
|---|---|---|---|---|
| 2 | bbb | 16 | 15 | 六班 |
| 3 | ccc | 17 | 15 | 七班 |
| 1 | aaa | 15 | 16 | 五班 |
| 3 | ccc | 17 | 16 | 七班 |
| 1 | aaa | 15 | 17 | 五班 |
| 2 | bbb | 16 | 17 | 六班 |
| 1 | aaa | 15 | 18 | 五班 |
| 2 | bbb | 16 | 18 | 六班 |
| 3 | ccc | 17 | 18 | 七班 |
結論如下:
不等值連接
若要連接表t1和t2,比較條件為t1.a不等於t2.a,那么數據庫會用t1中a列的所有元素逐個和t2中的a進行比較,如果不相等,則輸出該行。
自然連接
自然連接是一種特殊的等值連接,和等值連接差不多,區別在於:
自然連接會去掉重復的列;
自然連接要求比較的兩個列屬性必須相同,等值連接則不需要;
如果需要查出以下內容:
每個學生所對應的班級名稱
sql語句和等值連接差不多:
SELECT ts.*,tc.class_name FROM
T_student ts inner join T_class tc
ON
ts.class_id = tc.class_id
查詢結果如下:
| student_id | student_name | class_id | class_name |
|---|---|---|---|
| 1 | aaa | 15 | 五班 |
| 2 | bbb | 16 | 六班 |
| 3 | ccc | 17 | 七班 |
由此可見:
自然連接相當於在等值連接的基礎上,加了顯示的限定條件,從而實現列去重
外連接
外連接又分為左連接,右連接,全連接。
左連接
左連接以左表為基礎,顯示左表中的所有記錄(顯示的記錄條數=左表中記錄的條數)。再用左表中的指定列來和右表中的指定列比較,滿足則輸出值,不滿足則輸出NULL
如果需要查出以下內容:
每個學生所對應的班級名稱
此時就可用以下sql語句:
SELECT * FROM
T_student ts left join T_class tc
ON
ts.class_id = tc.class_id
查詢結果如下:
| student_id | student_name | class_id | class_id | class_name |
|---|---|---|---|---|
| 1 | aaa | 15 | 15 | 五班 |
| 2 | bbb | 16 | 16 | 六班 |
| 3 | ccc | 17 | 17 | 七班 |
但如果T_student表中增加一條字段:
| student_id | student_name | class_id |
|---|---|---|
| 4 | ddd | 20 |
此時再用上一條sql語句查詢,則結果變為:
| student_id | student_name | class_id | class_id | class_name |
|---|---|---|---|---|
| 1 | aaa | 15 | 15 | 五班 |
| 2 | bbb | 16 | 16 | 六班 |
| 3 | ccc | 17 | 17 | 七班 |
| 4 | ddd | 20 | NULL |
NULL |
結論如下:
左連接
以左表為基礎,顯示的記錄條數=左表中記錄條數。如果左表中選出的字段符合條件則顯示,否則顯示
NULL
右連接
與左連接恰恰相反。以右表為基礎,顯示記錄的條數=右表中記錄條數,然后和左表中的字段比較,符合條件則輸出,否則輸出NULL。
使用以下sql語句:
SELECT * FROM
T_student ts right join T_class tc
ON
ts.class_id = tc.class_id
查詢結果為:
| student_id | student_name | class_id | class_id | class_name |
|---|---|---|---|---|
| 1 | aaa | 15 | 15 | 五班 |
| 2 | bbb | 16 | 16 | 六班 |
| 3 | ccc | 17 | 17 | 七班 |
NULL |
NULL |
NULL |
18 | 八班 |
結論如下:
右連接
以右表為基礎,顯示記錄的條數=右表中記錄條數。如果左表中選出的字段符合條件則顯示,否則顯示
NULL
全連接
全連接類似於左連接和右連接的綜合,顯示記錄的條數=指定比較字段在兩個表中的不同種類數。對於空余字段則顯示NULL。
使用以下sql語句:
SELECT * FROM
T_student ts full join T_class tc
ON
ts.class_id = tc.class_id
查詢結果為:
| student_id | student_name | class_id | class_id | class_name |
|---|---|---|---|---|
| 1 | aaa | 15 | 15 | 五班 |
| 2 | bbb | 16 | 16 | 六班 |
| 3 | ccc | 17 | 17 | 七班 |
NULL |
NULL |
NULL |
18 | 八班 |
但如果T_student表中增加一條字段:
| student_id | student_name | class_id |
|---|---|---|
| 4 | ddd | 20 |
此時再用上一條sql語句查詢,則結果變為:
| student_id | student_name | class_id | class_id | class_name |
|---|---|---|---|---|
| 1 | aaa | 15 | 15 | 五班 |
| 2 | bbb | 16 | 16 | 六班 |
| 3 | ccc | 17 | 17 | 七班 |
| 4 | ddd | 20 | NULL |
NULL |
NULL |
NULL |
NULL |
18 | 八班 |
結論如下:
全連接
指定比較字段在兩個表中的不同種類數。對於空余字段則顯示
NULL。
交叉連接
交叉連接很簡單,就是兩個表做笛卡爾積。
如果不加where做選擇比較,那么顯示的記錄行數就是兩個表行數的乘積。
使用以下sql語句:
SELECT * FROM
T_student cross join T_class
或者:
SELECT * FROM
T_student,T_class
查詢結果為:
| student_id | student_name | class_id | class_id | class_name |
|---|---|---|---|---|
| 1 | aaa | 15 | 15 | 五班 |
| 2 | bbb | 16 | 15 | 六班 |
| 3 | ccc | 17 | 15 | 七班 |
| 1 | aaa | 15 | 16 | 五班 |
| 2 | bbb | 16 | 16 | 六班 |
| 3 | ccc | 17 | 16 | 七班 |
| 1 | aaa | 15 | 17 | 五班 |
| 2 | bbb | 16 | 17 | 六班 |
| 3 | ccc | 17 | 17 | 七班 |
| 1 | aaa | 15 | 18 | 五班 |
| 2 | bbb | 16 | 18 | 六班 |
| 3 | ccc | 17 | 18 | 七班 |
如果是有where進行選擇,那就先進行笛卡爾積,然后在笛卡爾積的結果中進行選擇(效率很差)。
結論如下:
交叉連接
沒有
where進行選擇,結果為兩個表的笛卡爾積
有where進行選擇,先做笛卡爾積,在笛卡爾積的結果中進行選擇
- Github:@crazyacking,Devin
- 郵箱:crazyacking@gmail.com
