mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| ID | int(11) | NO | PRI | 0 | |
| NAME | varchar(16) | YES | | NULL | |
| AGE | int(11) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set
mysql> desc sc;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| SID | int(11) | YES | | NULL | |
| CID | int(11) | YES | MUL | NULL | |
| SCORE | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+----------------+
4 rows in set
mysql> select * from student;
+-------+----------+-----+
| ID | NAME | AGE |
+-------+----------+-----+
| 10001 | Andy | 26 |
| 10002 | Bill | 27 |
| 10003 | Caroline | 34 |
| 10004 | David | 46 |
+-------+----------+-----+
4 rows in set
mysql> select * from sc;
+----+-------+-----+-------+
| ID | SID | CID | SCORE |
+----+-------+-----+-------+
| 1 | 10001 | 101 | 78 |
| 2 | 10001 | 102 | 67 |
| 3 | 10008 | 103 | 100 |
+----+-------+-----+-------+
3 rows in set
-----------------------------------------------------------------------------------------------------------------
內連接
mysql> select student.*, sc.* from student inner join sc on student.id = sc.sid;
+-------+------+-----+----+-------+-----+-------+
| ID | NAME | AGE | ID | SID | CID | SCORE |
+-------+------+-----+----+-------+-----+-------+
| 10001 | Andy | 26 | 1 | 10001 | 101 | 78 |
| 10001 | Andy | 26 | 2 | 10001 | 102 | 67 |
+-------+------+-----+----+-------+-----+-------+
2 rows in set
內連接等價於我們平時的自然連接,也就是:
mysql> select student.*, sc.* from student,sc where student.id = sc.sid;
+-------+------+-----+----+-------+-----+-------+
| ID | NAME | AGE | ID | SID | CID | SCORE |
+-------+------+-----+----+-------+-----+-------+
| 10001 | Andy | 26 | 1 | 10001 | 101 | 78 |
| 10001 | Andy | 26 | 2 | 10001 | 102 | 67 |
+-------+------+-----+----+-------+-----+-------+
2 rows in set
-----------------------------------------------------------------------------------------------------------------
左連接
考慮下面的需求,我想列出所有學生對應的成績,一個學生可能多個成績,也可能沒有成績。有多個成績把多個成績列出來,沒有成績的話,成績這些字段的值使用NULL填充。怎么解決這個問題?
使用左連接,student表 left join sc表,如下:
mysql> select student.*, sc.* from student left join sc on student.id = sc.sid;
+-------+----------+-----+------+-------+------+-------+
| ID | NAME | AGE | ID | SID | CID | SCORE |
+-------+----------+-----+------+-------+------+-------+
| 10001 | Andy | 26 | 1 | 10001 | 101 | 78 |
| 10001 | Andy | 26 | 2 | 10001 | 102 | 67 |
| 10002 | Bill | 27 | NULL | NULL | NULL | NULL |
| 10003 | Caroline | 34 | NULL | NULL | NULL | NULL |
| 10004 | David | 46 | NULL | NULL | NULL | NULL |
+-------+----------+-----+------+-------+------+-------+
5 rows in set
-----------------------------------------------------------------------------------------------------------------
右連接
考慮下面的需求,我想列出所有成績對應的學生,一個成績有對應的學生,也可能沒有對應的學生,比如這個學生開除了。有學生就把學生列出來,沒有學生的話,學生這些字段的值使用NULL填充。怎么解決這個問題?
使用右連接,student表 right join sc表,如下:
mysql> select student.*, sc.* from student right join sc on student.id = sc.sid;
+-------+------+------+----+-------+-----+-------+
| ID | NAME | AGE | ID | SID | CID | SCORE |
+-------+------+------+----+-------+-----+-------+
| 10001 | Andy | 26 | 1 | 10001 | 101 | 78 |
| 10001 | Andy | 26 | 2 | 10001 | 102 | 67 |
| NULL | NULL | NULL | 3 | 10008 | 103 | 100 |
+-------+------+------+----+-------+-----+-------+
3 rows in set
根據對稱性,A left join B 等價於 B right join A
-----------------------------------------------------------------------------------------------------------------
外連接
左連接也叫左外連接(同理右連接),這里的外連接也叫全外連接。
考慮下面的需求,我想列出所有學生對應的所有成績,這里存在學生可能沒有成績,成績也可能沒有對應的學生,沒有的話,也要列出來,這些字段的值使用NULL填充。
目前,mysql不支持外連接,解決辦法是使用union組合查詢,把左連接和右連接的結果合並。如下:
mysql> select student.*, sc.* from student left join sc on student.id = sc.sid union select student.*, sc.* from student right join sc on student.id = sc.sid;
+-------+----------+------+------+-------+------+-------+
| ID | NAME | AGE | ID | SID | CID | SCORE |
+-------+----------+------+------+-------+------+-------+
| 10001 | Andy | 26 | 1 | 10001 | 101 | 78 |
| 10001 | Andy | 26 | 2 | 10001 | 102 | 67 |
| 10002 | Bill | 27 | NULL | NULL | NULL | NULL |
| 10003 | Caroline | 34 | NULL | NULL | NULL | NULL |
| 10004 | David | 46 | NULL | NULL | NULL | NULL |
| NULL | NULL | NULL | 3 | 10008 | 103 | 100 |
+-------+----------+------+------+-------+------+-------+
6 rows in set
注意:這里的union自動去除了重復行,如果不想去除重復行,使用union all
-----------------------------------------------------------------------------------------------------------------
還有一點需要注意:就是on 之后的條件,如下:
mysql> select student.*, sc.* from student left join sc on student.id = sc.sid;
+-------+----------+-----+------+-------+------+-------+
| ID | NAME | AGE | ID | SID | CID | SCORE |
+-------+----------+-----+------+-------+------+-------+
| 10001 | Andy | 26 | 1 | 10001 | 101 | 78 |
| 10001 | Andy | 26 | 2 | 10001 | 102 | 67 |
| 10002 | Bill | 27 | NULL | NULL | NULL | NULL |
| 10003 | Caroline | 34 | NULL | NULL | NULL | NULL |
| 10004 | David | 46 | NULL | NULL | NULL | NULL |
+-------+----------+-----+------+-------+------+-------+
5 rows in set
mysql> select student.*, sc.* from student left join sc on student.id = sc.sid and sc.cid=101;
+-------+----------+-----+------+-------+------+-------+
| ID | NAME | AGE | ID | SID | CID | SCORE |
+-------+----------+-----+------+-------+------+-------+
| 10001 | Andy | 26 | 1 | 10001 | 101 | 78 |
| 10002 | Bill | 27 | NULL | NULL | NULL | NULL |
| 10003 | Caroline | 34 | NULL | NULL | NULL | NULL |
| 10004 | David | 46 | NULL | NULL | NULL | NULL |
+-------+----------+-----+------+-------+------+-------+
4 rows in set
mysql> select student.*, sc.* from student left join sc on student.id = sc.sid where sc.cid=101;
+-------+------+-----+----+-------+-----+-------+
| ID | NAME | AGE | ID | SID | CID | SCORE |
+-------+------+-----+----+-------+-----+-------+
| 10001 | Andy | 26 | 1 | 10001 | 101 | 78 |
+-------+------+-----+----+-------+-----+-------+
1 row in set
這里看出第二個查詢和第三個查詢的區別,換一種寫法就很清楚了。
mysql> select student.*, sc.* from student left join sc on (student.id = sc.sid and sc.cid=101);
+-------+----------+-----+------+-------+------+-------+
| ID | NAME | AGE | ID | SID | CID | SCORE |
+-------+----------+-----+------+-------+------+-------+
| 10001 | Andy | 26 | 1 | 10001 | 101 | 78 |
| 10002 | Bill | 27 | NULL | NULL | NULL | NULL |
| 10003 | Caroline | 34 | NULL | NULL | NULL | NULL |
| 10004 | David | 46 | NULL | NULL | NULL | NULL |
+-------+----------+-----+------+-------+------+-------+
4 rows in set
mysql> select student.*, sc.* from student left join sc on (student.id = sc.sid) where sc.cid=101;
+-------+------+-----+----+-------+-----+-------+
| ID | NAME | AGE | ID | SID | CID | SCORE |
+-------+------+-----+----+-------+-----+-------+
| 10001 | Andy | 26 | 1 | 10001 | 101 | 78 |
+-------+------+-----+----+-------+-----+-------+
1 row in set
mysql> select student.*, sc.* from student left join sc on (student.id = sc.sid where sc.cid=101);
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where sc.cid=101)' at line 1
-----------------------------------------------------------------------------------------------------------------
select student.*, sc.* from student left join sc on (student.id = sc.sid and sc.cid=101); 相當於:
1、內部連接
mysql> select student.*, sc.* from student inner join sc on student.id = sc.sid;
+-------+------+-----+----+-------+-----+-------+
| ID | NAME | AGE | ID | SID | CID | SCORE |
+-------+------+-----+----+-------+-----+-------+
| 10001 | Andy | 26 | 1 | 10001 | 101 | 78 |
| 10001 | Andy | 26 | 2 | 10001 | 102 | 67 |
+-------+------+-----+----+-------+-----+-------+
2 rows in set
2、選擇出sc.cid=101,再進行左連接,沒有成績的使用NULL填充
-----------------------------------------------------------------------------------------------------------------
select student.*, sc.* from student left join sc on (student.id = sc.sid) where sc.cid=101; 相當於:
1、左連接
mysql> select student.*, sc.* from student left join sc on student.id = sc.sid;
+-------+----------+-----+------+-------+------+-------+
| ID | NAME | AGE | ID | SID | CID | SCORE |
+-------+----------+-----+------+-------+------+-------+
| 10001 | Andy | 26 | 1 | 10001 | 101 | 78 |
| 10001 | Andy | 26 | 2 | 10001 | 102 | 67 |
| 10002 | Bill | 27 | NULL | NULL | NULL | NULL |
| 10003 | Caroline | 34 | NULL | NULL | NULL | NULL |
| 10004 | David | 46 | NULL | NULL | NULL | NULL |
+-------+----------+-----+------+-------+------+-------+
5 rows in set
2、再選出 sc.cid=101