【概念区分】笛卡尔积,自然连接,内连接,外连接(左,右,全)

时间:2024-02-01 07:37:27

本文章尝试解决一下问题

1.笛卡尔积存在的意义是什么?

2.”cross join 笛卡尔积“和”full join 全连接“和"inner join内连接"的区别在哪里?

3. 既然”连接条件“可以写在where字句里面,为什么还要用on关键字?

4.自然连接和内连接有什么关系吗?

 

 

1.笛卡尔积存在的意义是什么?

虽然”笛卡尔积“在实际问题中很少会用到,但”笛卡尔积“不仅仅存在数学意义,也存在现实意义的,比如集合A是一个班的学生,集合B是所有的选修课,A与B的笛卡尔积,表示了学生选择课程的所有可能性

mysql> select * from A;
+--------------+
| student_name |
+--------------+
| 张学友       |
| 刘德华       |
+--------------+
2 rows in set (0.00 sec)
mysql> select * from B;
+--------------+
| subject_name |
+--------------+
| 语文         |
| 数学         |
| 法律         |
+--------------+
3 rows in set (0.00 sec)

那么”学生选课“就拥有6种可能性,数学中的”排列组合“通过2*3=6得出来,MySQL用”corss join“来计算笛卡尔积

mysql> select * from A cross join B order by student_name;
+--------------+--------------+
| student_name | subject_name |
+--------------+--------------+
| 刘德华       | 数学         |
| 刘德华       | 法律         |
| 刘德华       | 语文         |
| 张学友       | 法律         |
| 张学友       | 语文         |
| 张学友       | 数学         |
+--------------+--------------+
6 rows in set (0.00 sec)

有同样效果的是

select * from A , B

 

2.”cross join 笛卡尔积“和”full join 全连接“和"inner join内连接"的区别在哪里?

cross join 象征着返回所有的情况,默认不使用 where进行过滤的,因为筛选之后就失去了”所有可能性“这种意义了,而 inner join默认使用on进行”匹配“,如果不使用on返回的是 cross join的所有可能性,也就失去了意义了

 

集合a(1,2,3),集合b(1,2,3)

1.笛卡尔积——返回3 * 3 =9 条记录,默认不用where

2.内连接——返回3条记录,默认使用on

 

3. 既然”连接条件“可以写在where字句里面,为什么还要用on关键字?

这是因为有两个原因

a. 更加清晰的把表与表之间”做连接”的条件,与其他条件区分开来,这好比小工的人力资源和行政是一体的,但公司大了,两者就可以分开,分工更清晰

b. 在 ”inner join 内连接“ 中,on和where虽然意义不同,但结果相同,但在 outer join 中,结果就不一样了,匹配条件放在where中是不会产生NULL值的

 

4.自然连接和内连接有什么关系吗?

“自然连接”和“内连接”的区别,在于对“重合的相同的部分”处理方式不同

1."natrual join 自然连接"的处理方式:既然重复了,就丢掉一份,好比distinct

2.“inner join 内连接”的处理方式:虽然重复,但两份都保留

假设有A,B两个集合,其中有两个字段是重复的

自然连接是“去重”,有点像distinct

mysql> select * from A natural join B;
+------+------+-----------+-----------+
| b    | c    | a         | d         |
+------+------+-----------+-----------+
| 1111 | 2222 | 刘德华    | 投名状    |
| 3333 | 4444 | 梁朝伟    | 花样年    |
+------+------+-----------+-----------+
2 rows in set (0.00 sec)

“内连接”的方式,是把所有重复的都保留(当然额外用where条件筛选是另外一回事了)

mysql> select * from A inner join B on A.b=B.b;
+-----------+------+------+------+------+-----------+
| a         | b    | c    | b    | c    | d         |
+-----------+------+------+------+------+-----------+
| 刘德华    | 1111 | 2222 | 1111 | 2222 | 投名状    |
| 梁朝伟    | 3333 | 4444 | 3333 | 4444 | 花样年    |
+-----------+------+------+------+------+-----------+
2 rows in set (0.00 sec)

 

最后附上一张关于连接的图