MySQL多表連接查詢
連接(join):將一張表中的行按照某個條件(連接條件)和另一張表中的行連接起來形成一個新行的過程。
根據連接查詢返回的結果,分3類:
內連接(inner join)
外連接(outer join)
交叉連接(cross join)
根據連接條件所使用的操作符,分2類:
相等連接(使用等號操作符)
不等連接(不使用等號操作符)
標准的連接語法:

注意:
在連接查詢中,一個列可能出現在多張表中,為了避免引起歧義,通常在列名前面加上表名或表別名作為前綴(例:s.sid、x.sid)---使用表別名作為前綴,可以使得SQL代碼較短,使用的內存更少(例:stu s,xuanke as x)。
搭建環境:模擬選課
mysql> select * from stu; +------+--------+---------+
| sid | sname | sphonum |
+------+--------+---------+
| 1 | 張三 | 110 |
| 2 | 李四 | 120 |
| 3 | 王五 | 130 |
+------+--------+---------+
3 rows in set (0.00 sec) mysql> select * from tea; +------+-----------+---------+
| tid | tname | tphonum |
+------+-----------+---------+
| 1113 | 相老師 | 1111 |
| 1114 | 馮老師 | 1112 |
+------+-----------+---------+
2 rows in set (0.00 sec) mysql> select * from course; +------+--------+
| cid | cname |
+------+--------+
| 1 | linux |
| 2 | mysql |
| 3 | hadoop |
+------+--------+
3 rows in set (0.00 sec) mysql> select * from xuanke; +------+------+------+--------+
| sid | tid | cid | xuefen |
+------+------+------+--------+
| 1 | 1113 | 2 | 2 |
| 1 | 1114 | 1 | 4 |
| 1 | 1113 | 3 | 6 |
| 2 | 1113 | 2 | 2 |
| 2 | 1114 | 1 | 2 |
| 2 | 1113 | 3 | 2 |
+------+------+------+--------+
6 rows in set (0.00 sec)
1、內連接inner join
只返回兩張表中所有滿足連接條件的行,即使用比較運算符根據每個表中共有的列的值匹配兩個表中的行。(inner關鍵字是可省略的)
①傳統的連接寫法:
在FROM子句中列出所有要連接的表的名字(進行表別名),以逗號分隔;
連接條件寫在WHERE子句中;
注意:一旦給表定義了別名,那么原始的表名就不能在出現在該語句的其它子句中
mysql> select s.sname,c.cname,t.tname,x.xuefen -> from stu s,tea t,course c,xuanke x -> where s.sid=x.sid and t.tid=x.tid and c.cid=x.cid; +--------+--------+-----------+--------+
| sname | cname | tname | xuefen |
+--------+--------+-----------+--------+
| 張三 | linux | 馮老師 | 4 |
| 李四 | linux | 馮老師 | 2 |
| 張三 | mysql | 相老師 | 2 |
| 李四 | mysql | 相老師 | 2 |
| 張三 | hadoop | 相老師 | 6 |
| 李四 | hadoop | 相老師 | 2 |
+--------+--------+-----------+--------+
6 rows in set (0.08 sec)
②使用on子句(常用):筆者比較喜歡的方法,因為覺得結構清晰明了。
mysql> select s.sname,t.tname,c.cname,x.xuefen -> from stu s -> join xuanke x -> on s.sid=x.sid -> join tea t -> on x.tid=t.tid -> join course c -> on c.cid=x.cid; 結果如上……
表之間的關系以JOIN指定,ON的條件與WHERE條件相同。
③使用using子句
mysql> select s.sname,t.tname,c.cname,x.xuefen -> from stu s -> join xuanke x -> using(sid) -> join tea t -> using(tid) -> join course c -> using(cid);
結果如上……
表之間的關系以join指定,using(連接列)進行連接匹配,類似於on。(相對用的會比較少)
2、外連接outer join
使用外連接不但返回符合連接和查詢條件的數據行,還返回不符合條件的一些行。
在MySQL數據庫中外連接分兩類(不支持全外連接):
左外連接、右外連接。(outer關鍵字可省略)。
共同點:都返回符合連接條件和查詢條件(即:內連接)的數據行
不同點:
①左外連接還返回左表中不符合連接條件,但符合查詢條件的數據行。(所謂左表,就是寫在left join關鍵字左邊的表)
②右外連接還返回右表中不符合連接條件,但符合查詢條件的數據行。(所謂右表,就是寫在right join關鍵字右邊的表)
mysql> select s.sname,x.xuefen -> from stu s -> left join xuanke x -> on s.sid=x.sid; +--------+--------+
| sname | xuefen |
+--------+--------+
| 張三 | 2 |
| 張三 | 4 |
| 張三 | 6 |
| 李四 | 2 |
| 李四 | 2 |
| 李四 | 2 |
| 王五 | NULL |
+--------+--------+
7 rows in set (0.00 sec)
解析:stu表是左表,xuanke表是右表:left join是左連接,stu表中”王五”沒有選課,在xueke表中沒有數據行,不符合連接條件,返回符合查詢條件的數據行,所以xuefen為null。
mysql> select s.sname,x.xuefen -> from xuanke x -> right join stu s -> on x.sid=s.sid; 結果如上(用的是右連接的方式)
給連接查詢附加條件:
1、寫在WHERE子句中
2、使用AND和連接條件寫在一起
!!!但是:
對於內連接,兩種寫法結果相同;
對於外連接,兩種寫法結果不同。
mysql> select s.sname,x.xuefen -> from stu s -> left join xuanke x -> on x.sid=s.sid -> where sname='張三'; +--------+--------+
| sname | xuefen |
+--------+--------+
| 張三 | 2 |
| 張三 | 4 |
| 張三 | 6 |
+--------+--------+
3 rows in set (0.01 sec) mysql> select s.sname,x.xuefen -> from (select * from stu where sname='張三') s -> left join xuanke x -> on x.sid=s.sid; +--------+--------+
| sname | xuefen |
+--------+--------+
| 張三 | 2 |
| 張三 | 4 |
| 張三 | 6 |
+--------+--------+
3 rows in set (0.00 sec)
①先連接后過濾
select ……from ……
left join ……
on 連接條件
where 過濾條件;
②先過濾后連接
select ……from (select ……from ……where 過濾條件)
left join ……
on 連接條件;
3、交叉連接—笛卡爾積
因為沒有連接條件,所進行的表與表間的所有行的連接。
特點:
①連接查詢沒有寫任何連接條件
②結果集中的總行數就是兩張表中總行數的乘積(笛卡爾積)
注意:在實際中,應該要避免產生笛卡爾積的連接,特別是對於大表
mysql> select * from stu,tea,course,xuanke; …… …… 108 rows in set (0.00 sec)
若是想專門產生笛卡爾積,可以使用交叉連接
mysql> select *
-> from stu -> crosss join tea; +------+--------+---------+------+-----------+---------+
| sid | sname | sphonum | tid | tname | tphonum |
+------+--------+---------+------+-----------+---------+
| 1 | 張三 | 110 | 1113 | 相老師 | 1111 |
| 1 | 張三 | 110 | 1114 | 馮老師 | 1112 |
| 2 | 李四 | 120 | 1113 | 相老師 | 1111 |
| 2 | 李四 | 120 | 1114 | 馮老師 | 1112 |
| 3 | 王五 | 130 | 1113 | 相老師 | 1111 |
| 3 | 王五 | 130 | 1114 | 馮老師 | 1112 |
+------+--------+---------+------+-----------+---------+
6 rows in set (0.00 sec)
