MySQL两个表的亲密接触-连接查询的原理

关系型数据库还有一个重要的概念:Join(连接) 。使用Join有好处 , 也会坏处 , 只有我们明白了其中的原理 , 才能更多的使用Join 。切记不可以:
业务之上 , 再复杂的查询也在一个连表语句中完成 。
敬而远之 , DBA每次上报的慢查询都是连接查询导致的 , 我再也不用了 。
连接简介连接的本质我们先来创建两个简单的表 , 再初始化一些数据
 CREATE TABLE t1 (m1 int, n1 varchar(1));CREATE TABLE t2 (m2 int, n2 varchar(1));INSERT INTO t1 VALUES(1, 'a'), (2 , 'b') ,(3 ,'c') ; INSERT INTO t2 VALUES(2 , 'b'), (3 , 'c '),(4 , 'd');从本质上来说 , 连接就是把各个表的数据都取出来进行匹配 , t1 和 t2 的两个表连接起来就是这样的:
 

MySQL两个表的亲密接触-连接查询的原理

文章插图
 
连接语法:
select * from t1, t2;如果乐意 , 我们可以连接任意数量的表 。但是如果不加任何限制条件的话 , 这个数据量是非常大的 , 我们现实中使用都是会加上限制条件的 。我们来看下下面这条语句
select * from t1,t2 where t1.m1 > 1 and t1.m1 = t2.m2 and t2.n2 = 'c';这个连接查询的执行过程大致如下
首先确定第一个需要查询 表称为驱动表(t1)
步骤1中从驱动表 (t1) 中每获得一条记录 , 都要去被驱动表 (t2) 中查询匹配 。
从上面的步骤 , 可以看出上述的连表查询我们需要查询一次t1 , 两次t2 。也就是说 , 两表的连接查询中 , 需要查询一次驱动表 , 被驱动表需要查询多次 。
这里需要注意下 , 并不是将所有满足条件的驱动表记录先查询出来放到一个地方 , 然后再去被驱动表中查询 , (如果满足条件的驱动表中的数据非常多 , 那要需要多大的内存呀 。) 所以是每获得一条驱动表记录就去被驱动表中查询 。
内连接和外连接我们再来创建两个表 , 并插入一些数据
CREATE TABLE student ( number INT NOT NULL Auto_increment comment'学号',name varchar (5) COMMENT '姓名',major varchar (30) comment '专业',PRIMARY KEY (number));CREATE TABLE score ( number INTcomment'学号',subject varchar (30) COMMENT '科目',score TINYINTcomment '成绩',PRIMARY KEY (number, subject));INSERT INTO `student` (`number`, `name`, `major`) VALUES ('20230301', '小赵', '计算机科学');INSERT INTO `student` (`number`, `name`, `major`) VALUES ('20230302', '小钱', '通信');INSERT INTO `student` (`number`, `name`, `major`) VALUES ('20230303', '小孙', '土木工程');INSERT INTO `score` (`number`, `subject`, `score`) VALUES ('20230301', '高等数学', '60');INSERT INTO `score` (`number`, `subject`, `score`) VALUES ('20230301', '英语', '70');INSERT INTO `score` (`number`, `subject`, `score`) VALUES ('20230302', '高等数学', '80');INSERT INTO `score` (`number`, `subject`, `score`) VALUES ('20230302', '英语', '90');如果我们想把所有的学生的成绩都查出来 , 只需要这样执行:
select s1.number, s1.name, s1.major, s2.subject, s2.scorefrom student as s1 , score as s2 where s1.number = s2.number;有个问题就是小孙因为某些原因没有参加考试 , 所以在结果表中没有对应 的成绩记录 。如果老师想查看所有学生的考试成绩 , 即使是缺考的学生 他们的成绩也应该展示出来 。
为了解决这个问题 , 就有了内连接和外连接的概念:
  • 对于内连接的两个表 , 若驱动表中的记录在被驱动表找不到匹配的记录 , 则该记录不会加入到最后的结果集 。前面提到的连接都是内连接 。
  • 对于外连接的两个表 , 时驱动表中的记录在被驱动表中没有匹配的记录 , 也仍然需要加入到结果集 。
MySQL 中 , 根据选取的驱动表的不同 , 外连接可以细分为
  • 左外连接 选取左侧的表为驱动表 。
  • 右外连接·选取右侧的表为驱动表 。
当我们使用外连接的时候 有时候我们也不想把驱动表的全部记录都加入到最后的结果集中 , 这个时候我们就要使用过滤条件了 。


推荐阅读