轉載請註明出處!!
以前數據錶鏈接操做多使用逗號或者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的鏈接就清晰了。
若有不許確的地方請留言指教