Mysql中的七种常用查询连接详解

Posted 爱吃面的猫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql中的七种常用查询连接详解相关的知识,希望对你有一定的参考价值。

目录

一、概述

二、连接查询的分类

三、七种常用连接查询详解

1、笛卡尔积:

2、内连接

2.1隐式与显式连接

 2.2等值连接

 2.3非等值连接

 2.4自连接

3外连接

3.1左外连接:

 3.2右外连接:

3.3全外连接


一、概述

       在实际开发中,大部分的情况下都不是从单表中查询数据,一般都是多张表联合查询取出最终的结果。一个业务都会对应多张表,比如:学生和班级,起码两张表。(避免产生数据的冗余)。

内连接和外连接的区别

       1、内连接:

        假设A和B表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是内连接。AB两张表没有主副之分,两张表是平等的。

        2、外连接:

        假设A和B表进行连接,使用外连接的话, AB两张表中有一张表是主表,一张表是副表,主要查询主表中的数据,捎带着查询副表。当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配。
 

二、连接查询的分类

1、根据语法出现的年代来划分:

  •  sql97--仅仅支持内连接(一些老的DBA可能还在使用这种语法。)
  •  sql99--推荐使用,支持左外+右外(左外+右外)+交叉

2、根据功能划分分类:

  • 交叉连接:笛卡尔积。
  • 内连接:等值连接、非等值连接、自连接。(还可分为隐式【无join】和显式【有join】)
  • 外连接:左外连接(左连接)、右外连接(右连接)、全连接。

3、 生成测试数据

      执行下面的sql语句生成student表和teacher表,两表通过teacher_id关联。

create table student(
    id int(3) not null primary key,
    name char(6) not null,
    age int(2) not null,
    teacher_id int(3) not null
);
create table teacher(
    id int(3) not null primary key,
    name char(6) not null,
    age int(2) not null,
    class_id int(3) not null
);
插入值 id 姓名 年龄 教师id

insert into student values(1, '刘峰', 20, 1);
insert into student values(2, '李福', 22, 2);
insert into student values(3, '王紫', 21, 3);
insert into student values(4, '赵兰', 24, 4);
insert into student values(5, '夏日', 23, 5);
insert into student values(6, '詹启', 22, 6);
insert into student values(7, '刘娜', 24, 4);
insert into student values(8, '王恒', 23, 5);
insert into student values(9, '晓飞', 22, 6);

插入值 id 姓名 年龄 班级id

insert into teacher values(1, '夏晴', 36, 1);
insert into teacher values(2, '李淳', 32, 2);
insert into teacher values(3, '张叶', 34, 3);
insert into teacher values(4, '鹿雪', 37, 3);
insert into teacher values(5, '刘花', 36, 2);
insert into teacher values(6, '贾义', 34, 1);
执行下面查询语句,student表和teacher表如下:

select * from student;
select * from teacher;

                    student表                                                              teacher表

      

三、七种常用连接查询详解

1、笛卡尔积:

      笛卡尔积也称交叉连接,交叉连接是内连接的一种。

      假设集合A=a,b,集合B=0,1,2,则两个集合的笛卡尔积为(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)。如果A表示某学校学生的集合,B表示该学校所有教师的集合,则A与B的笛卡尔积表示学生选择老师所有可能的情况。

      笛卡尔积特点:它不使用任何匹配或者选取条件,而是直接将一个数据源中的每个行与另一个数据源的每个行 一 一 匹配。

      重点记:

      笛卡尔积:用的比较少,因为存在重复数据
      笛卡尔积:一个表的每条数据都和另一个表的所有数据匹配一次
      结       果: 一表 9 条 乘以 另一表 6 条 = 54 条

1.1 案例如下:

     查询学生对应的老师

     select * from student ,teacher;

     学生表 中数据每 1 个学生都和 教师表 中的 所有教师 都匹配一次。


       问题:
       当两张表进行连接查询的时候,没有任何条件进行限制,最终的查询结果条数是两张表记录条数的乘积。这就是笛卡尔积现象。 查询出来的结果是两张表的记录的乘积 9*6=54,许多数据是无效数据。如何避免笛卡尔积现象?

       解决方案: 增加加条件进行过滤,但只会显示有效记录。此时也是隐式(无join)内连接

       根据教师id查询学生对应的选课老师
       select st.*,th.* from student st ,teacher th where st.teacher_id = th.id;

       

       注意:使用as可以对表和字段起别名,关于表的别名的优点:执行效率高;可读性好。
                 其中st是student的表的别名,原是from student as st,其中as可以省略。
                 其中th是teacher的表的别名,原是from teacher as th,其中as可以省略。

2、内连接

     内连接,取的就是两张表的交集。

     

     内连接又分为等值连接、非等值连接、自连接。(还可分为隐式【无join】和显式【有join】)

2.1隐式与显式连接

     隐式(无join)连接语法:select 字段 from 表A, 表B​ where 消除笛卡尔积的连接条件

     案例:根据教师id查询学生对应的选课老师
     select st.*,th.* from student st ,teacher th where st.teacher_id = th.id;

     

       显式(有join)连接语法:select 字段* from 表A 别名 INNER(可以省略) JOIN 表B 别名 ON 消除笛卡尔积的连接条件

      案例:根据教师id查询学生对应的选课老师

      select st.*,th.* from student st inner join teacher th on st.teacher_id = th.id;

      select st.*,th.* from student st join teacher th on st.teacher_id = th.id;(inner 可以省略)

     

 2.2等值连接

     等值连接的最大的特点就是:条件是等量关系,SQL99(最常用)。

     等值连接语法
     select 字段* from 表1  INNER(可以省略) JOIN 表2  ON 消除笛卡尔积的连接条件A=B

     案例:根据教师id查询学生对应的选课老师

     select st.*,th.* from student st join teacher th on st.teacher_id = th.id;

     

 2.3非等值连接

     非等值连接的最大的特点就是:条件不是是等量关系,SQL99(最常用)。

     非等值连接语法
     select 字段* from 表1  INNER(可以省略) JOIN 表2  ON 消除笛卡尔积的连接条件

     案例:查询教师id在4-6之间所教的学生和老师信息
select st.*,th.* from student st join teacher th on st.teacher_id = th.id and th.id between 4 and 6;

     

 2.4自连接

     自连接的最大的特点:就是一张表看做两张表,自己连接自己

     实质就是等值连接,只不过是连接表本身。

     案例:查询学生id和教师id相同的学生
     select s.*,st.teacher_id from student s,student st where s.id = st.teacher_id;

3外连接

    外连接又分为左外连接、右外连接、全连接

    左外连接(LEFT OUTER JOIN),简称左连接(LEFT JOIN)

    右外连接(RIGHT OUTER JOIN),简称右连接(RIGHT JOIN)

    全外连接(FULL OUTER JOIN),简称全连接(FULL JOIN)

    向 student 表 中插入两条语句,teacher_id的 13 和 15 在teacher中是不存在的。
    INSERT INTO `cqyddx`.`student`(`id`, `name`, `age`, `teacher_id`) VALUES (10, '夏雨', 21,13);
    INSERT INTO `cqyddx`.`student`(`id`, `name`, `age`, `teacher_id`) VALUES (11, '冬雪', 22,15);

    插入 teacher 表 三条语句,id分别为
    INSERT INTO `cqyddx`.`teacher`(`id`, `name`, `age`, `class_id`) VALUES (7, '付霞', 34, 4);
    INSERT INTO `cqyddx`.`teacher`(`id`, `name`, `age`, `class_id`) VALUES (8, '郝仁', 33, 5);
    INSERT INTO `cqyddx`.`teacher`(`id`, `name`, `age`, `class_id`) VALUES (9, '赵刚', 35, 7);

3.1左外连接:

     左外连接:left join 或 left outrer join  (outer可以省略)

     左外连接:左边的是主表,左表数据全部显示,右表显示符合ON后的条件的数据,不符合的用NULL代替。

       

       select * from student st left join teacher th on st.teacher_id = th.id;(outer可以省略)

      

      通过查询结果发现,左外连接查询的是 左表独有的数据 加上 两表共有的数据

     

      左外特殊情况:返回没有匹配的记录

     

       案例:查询没有教师的学生信息

      select * from student st left join teacher th on st.teacher_id = th.id where th.id is null;

      

      通过查询发现,左连接查询的为左表独有的数据。

 3.2右外连接:

      右外连接:right join 或 right outrer join  (outer可以省略)

      右外连接:右边边的是主表,右边表数据全部显示,左边表显示符合ON后的条件的数据,不符合的用NULL代替。

       

       select * from student st right join teacher th on st.teacher_id = th.id;(outer可以省略)

       

       通过结果发现,右外连接查询的是 右表独有的数据 加上 两表共有的数据

     

       右外特殊情况:返回没有匹配的记录

        

       案例:查询没有学生的教师信息

       select * from student st right join teacher th on st.teacher_id = th.id where st.teacher_id is null;

       

       通过查询发现,右连接查询的为右表独有的数据。

3.3全外连接

      全外连接:full join 或 full outer join(outer可以省略),但mysql不支持,可以使用union组合并去重实现。 
      简单理解

      全外接查询:就是 左表独有的数据 加上 右表独有的数据

      

    select * from student st left join teacher th on st.teacher_id = th.id where th.id is null
    union 
    select * from student st right join teacher th on st.teacher_id = th.id where st.teacher_id is null

    

3.4全连接

      全连接:full join 或 full outer join(outer可以省略),但Mysql不支持,可以使用union组合并去重实现。

       简单理解

       全连接查询的是 左表所有的数据  加上 右表所有的数据 并去重。 

       
       select * from student st left join teacher th on st.teacher_id = th.id
         union 
       select * from student st right join teacher th on st.teacher_id = th.id

       

总结:mysql存在七种连接,分别是内连接、左外连接、左外连接特殊情况、右外连接、右外连接特殊情况、全连接、全外连接。总结在一起就是内连接、左外连接、右外连接、全外连接。

MySQL中的七种常见通用的join查询

常见通用的join查询

在这里插入图片描述
在这里插入图片描述

我用下面两张表来演示上面七种情况:

t_nation表
在这里插入图片描述
t_hero表
在这里插入图片描述

1.A∩B (内连接 B图)

select * from t_hero as h join
 t_nation n on h.hc_id=n.n_id;

在这里插入图片描述

2.A-B ( D图)

select * from t_hero as h left join 
t_nation as n on h.hc_id=n.n_id where n.n_id is null;

在这里插入图片描述

3.B-A (E图)

select * from t_hero as h right join 
t_nation as n on h.hc_id=n.n_id where h.h_id is null;

在这里插入图片描述

4.A∪B (F图 全外连接 mysql不支持)

select * from t_hero as h right join 
t_nation as n on h.hc_id=n.n_id
union
select * from t_hero as h left join 
t_nation as n on h.hc_id=n.n_id;

在这里插入图片描述

5.A-B∪ A∩B (A图 左连接)

select * from t_hero as h left join
 t_nation as n  on h.hc_id=n.n_id 

在这里插入图片描述

6.B-A∪ A∩B (B图 右连接)

select * from t_hero as h right join
 t_nation as n  on h.hc_id=n.n_id 

在这里插入图片描述

7.A-B∪B-A (G图)

select * from t_hero as h right join
 t_nation as n  on h.hc_id=n.n_id where h.hc_id is null
union
select * from t_hero as h left join 
t_nation as n  on h.hc_id=n.n_id where n.n_id is null;

在这里插入图片描述

以上是关于Mysql中的七种常用查询连接详解的主要内容,如果未能解决你的问题,请参考以下文章

MySQL常用的七种join查询

MySQL常用的七种join查询

MySQL常用的七种join查询

MySQL常用的七种join查询

MySQL索引失效的七种情况

MySQL索引失效的七种情况