MySQL的幾種鏈接 join/inner join/cross join/逗號/left join/right join/natural join

轉載請註明出處!!
以前數據錶鏈接操做多使用逗號或者join,對幾種鏈接的概念一直渾渾噩噩,最近研究了一波,把這些鏈接的區別搞明白了。
 
鏈接:A xjoin B(主表 操做 關聯表)
 select過程:from->where->group by->having->order by->limit
在不使用on語法時,join、inner join、逗號、cross join結果相同,都是取2個表的笛卡爾積。逗號與其餘操做符優先級不一樣,因此有可能產生語法錯誤,儘可能減小用逗號
 
join、inner join、cross join支持on和using語法, 逗號不支持on和using語法
on語法:篩選鏈接後的結果,兩表的對應列值相同纔在結果集中,能夠經過and鏈接多個列值的匹配要求,列名能夠不一樣
     select * from tb_test1 inner join tb_student on tb_test1.id=tb_student.id;
using語法:篩選鏈接後的結果,兩表的對應列值相同纔在結果集中,括號內用多個列名要求用逗號鏈接,列名必須相同
     select * from tb_test1 cross join tb_student using(id);
 
僅MySQL中!:(MySQL中沒有全外鏈接,用UNION操做實現吧)
join=inner join=cross join(笛卡爾積)
left join=left outer join
right join=right outer join
 
sample數據:
 
 select * from tb_test1;
+----+-----------+--------+-------+
| id | name      | gender | score |
+----+-----------+--------+-------+
|  1 | 李毅      | 男     | 95.30 |
|  2 | 二丫      | 女     | 95.30 |
|  3 | 張三      | 女     | 95.30 |
|  4 | 李四      | 女     | 95.30 |
|  7 | 胡魯瓦    | 男     | 95.30 |
|  9 | 后羿      | 男     | 95.30 |
+----+-----------+--------+-------+
 
 select * from tb_student;
+----+--------+--------+------------+
| id | name   | gender | birthday   |
+----+--------+--------+------------+
|  1 | 李毅   | 男     | 1988-03-20 |
|  2 | kevin  | 男     | 1987-08-23 |
|  3 | marry  | 女     | 1989-11-25 |
|  4 | lucy   | 女     | 1989-11-25 |
|  5 | lily   | 女     | 1992-01-25 |
+----+--------+--------+------------+
 

natural join:天然鏈接(不容許帶on/using)
     natrual join:全天然鏈接,對左右2個表相同名字的列進行等值匹配,不可用on,using操做指定,自動刪除多餘重名列
     natrual left join:左天然鏈接,保留2個表的列(刪除多餘重名列),以左表爲準,不存在匹配的右表列,值置爲NULL
     natrual right join:和左天然鏈接相反
 
select * from tb_test1 natural join tb_student;
+----+--------+--------+-------+------------+
| id | name   | gender | score | birthday   |
+----+--------+--------+-------+------------+
|  1 | 李毅   | 男     | 95.30 | 1988-03-20 |
+----+--------+--------+-------+------------+
 
select * from tb_test1 natural left join tb_student;
+----+-----------+--------+-------+------------+
| id | name      | gender | score | birthday   |
+----+-----------+--------+-------+------------+
|  1 | 李毅      | 男     | 95.30 | 1988-03-20 |
|  2 | 二丫      | 女     | 95.30 | NULL       |
|  3 | 張三      | 女     | 95.30 | NULL       |
|  4 | 李四      | 女     | 95.30 | NULL       |
|  7 | 胡魯瓦    | 男     | 95.30 | NULL       |
|  9 | 后羿      | 男     | 95.30 | NULL       |
+----+-----------+--------+-------+------------+
 
select * from tb_test1 natural right join tb_student;
+----+--------+--------+------------+-------+
| id | name   | gender | birthday   | score |
+----+--------+--------+------------+-------+
|  1 | 李毅   | 男     | 1988-03-20 | 95.30 |
|  2 | kevin  | 男     | 1987-08-23 |  NULL |
|  3 | marry  | 女     | 1989-11-25 |  NULL |
|  4 | lucy   | 女     | 1989-11-25 |  NULL |
|  5 | lily   | 女     | 1992-01-25 |  NULL |
+----+--------+--------+------------+-------+
 

inner join:內鏈接(不帶on/using時作笛卡爾積)
     主表和關聯表的笛卡爾積結果,經過on或者using操做篩選結果集(先求笛卡爾積,後篩選,因此性能上和where同樣),2個表的全部列都被保存
 
 select * from tb_student a join tb_test1 b on a.id=b.id;
+----+--------+--------+------------+----+--------+--------+-------+
| id | name   | gender | birthday   | id | name   | gender | score |
+----+--------+--------+------------+----+--------+--------+-------+
|  1 | 李毅   | 男     | 1988-03-20 |  1 | 李毅   | 男     | 95.30 |
|  2 | kevin  | 男     | 1987-08-23 |  2 | 二丫   | 女     | 95.30 |
|  3 | marry  | 女     | 1989-11-25 |  3 | 張三   | 女     | 95.30 |
|  4 | lucy   | 女     | 1989-11-25 |  4 | 李四   | 女     | 95.30 |
+----+--------+--------+------------+----+--------+--------+-------+
 
select * from tb_student a join tb_test1 b on a.gender=b.gender and a.name=b.name;
+----+--------+--------+------------+----+--------+--------+-------+
| id | name   | gender | birthday   | id | name   | gender | score |
+----+--------+--------+------------+----+--------+--------+-------+
|  1 | 李毅   | 男     | 1988-03-20 |  1 | 李毅   | 男     | 95.30 |
|  6 | 李毅   | 男     | 1985-10-11 |  1 | 李毅   | 男     | 95.30 |
+----+--------+--------+------------+----+--------+--------+-------+
 
 

left join:左外鏈接(必須帶on/using,等價與left outer join)
     左表爲主表,保留所有記錄所有列,右表爲關聯表,加上on操做以外的其餘列,符合on條件的記錄鏈接上
 
on和where的區別(在外鏈接時有差異):on和where在性能上不存在差別,都是在笛卡爾積後篩選,但on在from階段,屬於join操做,先於where。因此當left join鏈接時,雖然左表的列不符合on條件,也必須保留,只是該記錄右表全是null。而where對鏈接後的結果作篩選,不符合條件的直接剔除
 
select * from tb_student a left join tb_test1 b on a.id=b.id;
+----+--------+--------+------------+------+--------+--------+-------+
| id | name   | gender | birthday   | id   | name   | gender | score |
+----+--------+--------+------------+------+--------+--------+-------+
|  1 | 李毅   | 男     | 1988-03-20 |    1 | 李毅   | 男     | 95.30 |
|  2 | kevin  | 男     | 1987-08-23 |    2 | 二丫   | 女     | 95.30 |
|  3 | marry  | 女     | 1989-11-25 |    3 | 張三   | 女     | 95.30 |
|  4 | lucy   | 女     | 1989-11-25 |    4 | 李四   | 女     | 95.30 |
|  5 | lily   | 女     | 1992-01-25 | NULL | NULL   | NULL   |  NULL |
|  6 | 李毅   | 男     | 1985-10-11 | NULL | NULL   | NULL   |  NULL |
+----+--------+--------+------------+------+--------+--------+-------+
 
select * from tb_student a left join tb_test1 b on a.id=b.id and a.id<4;
+----+--------+--------+------------+------+--------+--------+-------+
| id | name   | gender | birthday   | id   | name   | gender | score |
+----+--------+--------+------------+------+--------+--------+-------+
|  1 | 李毅   | 男     | 1988-03-20 |    1 | 李毅   | 男     | 95.30 |
|  2 | kevin  | 男     | 1987-08-23 |    2 | 二丫   | 女     | 95.30 |
|  3 | marry  | 女     | 1989-11-25 |    3 | 張三   | 女     | 95.30 |
|  4 | lucy   | 女     | 1989-11-25 | NULL | NULL   | NULL   |  NULL |
|  5 | lily   | 女     | 1992-01-25 | NULL | NULL   | NULL   |  NULL |
|  6 | 李毅   | 男     | 1985-10-11 | NULL | NULL   | NULL   |  NULL |
+----+--------+--------+------------+------+--------+--------+-------+
 
select * from tb_student a left join tb_test1 b on a.id=b.id where a.id<4;
+----+--------+--------+------------+------+--------+--------+-------+
| id | name   | gender | birthday   | id   | name   | gender | score |
+----+--------+--------+------------+------+--------+--------+-------+
|  1 | 李毅   | 男     | 1988-03-20 |    1 | 李毅   | 男     | 95.30 |
|  2 | kevin  | 男     | 1987-08-23 |    2 | 二丫   | 女     | 95.30 |
|  3 | marry  | 女     | 1989-11-25 |    3 | 張三   | 女     | 95.30 |
+----+--------+--------+------------+------+--------+--------+-------+
 

right join:右外鏈接,和左外鏈接相反
 
 
之後再使用MySQL的鏈接就清晰了。
若有不許確的地方請留言指教
相關文章
相關標籤/搜索