MySQL语法使用-连接查询-《MySQL学习笔记》

admin 2025-11-03 23:35:17 数据库 来源:ZONE.CI 全球网 0 阅读模式
  • 1、连接查询概念
    • 1.1 为什么需要连接查询
    • 1.2 连接的概念
    • 1.3 连接的过程
  • 2、内连接和外连接
    • 2.1 内连接和外连接的概念
    • 2.2 内连接
    • 2.3 外连接
      • 2.3.1 左连接
      • 2.3.2 右连接
  • 3、自连接
    • 3.1 表的别名
    • 3.2 自连接
  • 4、连接查询多张表时如何选择驱动表
  • 参考

    1、连接查询概念

    1.1 为什么需要连接查询

    前面我们举例时总是拿学生信息表和学生成绩表举例,这两个表通过外键学号连接,为什么不能把这两张表合成一张表,查询的时候直接针对单表查询,而不是搞什么子查询和连接查询呢?将两张表合为一张表,表中记录学生的每一门课程和对应的得分,合并后的表如下:student_merge表

    number name sex id_number department major enrollment_time subject score
    20180101 杜子腾 158177199901044792 计算机学院 计算机科学与工程 2018-09-01 母猪的产后护理 78
    20180101 杜子腾 158177199901044792 计算机学院 计算机科学与工程 2018-09-01 论萨达姆的战争准备 88
    20180102 杜琦燕 151008199801178529 计算机学院 计算机科学与工程 2018-09-01 母猪的产后护理 100
    20180102 杜琦燕 151008199801178529 计算机学院 计算机科学与工程 2018-09-01 论萨达姆的战争准备 98
    20180103 范统 17156319980116959X 计算机学院 软件工程 2018-09-01 母猪的产后护理 59
    20180103 范统 17156319980116959X 计算机学院 软件工程 2018-09-01 论萨达姆的战争准备 61
    20180104 史珍香 141992199701078600 计算机学院 软件工程 2018-09-01 母猪的产后护理 55
    20180104 史珍香 141992199701078600 计算机学院 软件工程 2018-09-01 论萨达姆的战争准备 46
    20180105 范剑 181048200008156368 航天学院 飞行器设计 2018-09-01 NULL NULL
    20180106 朱逸群 197995199801078445 航天学院 电子信息 2018-09-01 NULL NULL

    以为合并成一张表,单表查询会更方便,其实不然,由于一个学生会有多门课程,每一个课程占用一条记录,而且添加一个学生的课程成绩时,需要把这个学生的基本信息再重复写一遍,因此合并后的单表查询会有以下问题:

    • 浪费存储空间;
    • 由于新增一条记录需要重复录入学生的基本信息,后期维护困难。

    其实这里更多的是要分库分表的原因的逆向解释,正因为如此才会把student_merge表拆分成两张表,减少存储冗余信息,提高查询效率,降低维护成本,分库分表在MySQL性能调优专栏再介绍。

    1.2 连接的概念

    多表查询,我们可以使用子查询和连接查询。连接查询的定义:连接查询就是将多张表的记录取出来进行全排列组合,然后将全排列后的记录根据过滤条件进行筛选,筛选后的记录放入结果集中,连接查询后的表自然拥有所有表的列。为了介绍连接查询的概念,这里新增两张表:t1t2进行举例说明:表t1

    t1_col1 t1_col2
    1 a
    2 b
    3 c

    表t2

    t2_col1 t2_col2
    2 b
    3 c
    4 d

    t1t2进行连接,意思就是t1t2的每条记录拿出来进行全排列,全排列后的表包含t1t2里所有的列,示意图如下:image.png连接查询的SQL语句有以下几种写法,推荐第一种写法:

    1. # 连接查询写法1
    2. SELECT * FROM t1, t2;
    3. # 连接查询写法2
    4. SELECT t1.t1_col1, t1.t1_col2, t2.t2_col1, t2.t2_col2 FROM t1, t2;
    5. # 连接查询写法3
    6. SELECT t1_col1, t1_col2, t2_col1, t2_col2 FROM t1, t2;
    7. # 连接查询写法4
    8. SELECT t1.*, t2.* FROM t1, t2;

    注意表名.列名这种写法是当遇到两张表有相同列名时加以区分的写法。

    1.3 连接的过程

    上面介绍连接查询会根据查询条件将全排列的记录进行过滤,下面举个连接查询的例子说明连接查询的过程:

    1. SELECT * FROM t1, t2 WHERE t1.t1_col1 > 1 AND t1.t1_col1 = t2.t2_col1 AND t2.t2_col2 < 'd';

    过滤条件有三个:

    • t1.t1_col1 > 1;
    • t1.t1_col1 = t2.t2_col1;
    • t2.t2_col2 < ‘d’;

    上面的连接查询的具体过程如下:(1)t1表的查询首先确定第一个要查询的表,这个表称为驱动表,t1表就是我们上面例子的驱动表。在t1表,结合过滤条件中的第一条是仅针对t1表的,根据t1.t1_col1 > 1t1表满足过滤条件的记录仅有两条:

    t1_col1 t1_col2
    2 b
    3 c

    (2)t2表的查询上面驱动表t1经过筛选后的每一条记录,都要结合过滤条件与t2表的每一条记录进行全排列,因此要在t2表中进行2次查询,t2表也称为被驱动表

    • 第一次查询

    t1表中的第一行记录,结合两个过滤条件,t1.t1_col1 = t2.t2_col1t2.t2_col1=2t2.t2_col2 < 'd't2表中满足条件的仅是t2表中的第二行记录,因此将t1表中的第一行记录与t2表中的第二行记录匹配,结果如下:

    t1_col1 t1_col2 t2_col1 t2_col2
    2 b 2 b
    • 第二次查询

    t1表中的第二行记录,结合两个过滤条件,t1.t1_col1 = t2.t2_col1t2.t2_col1=3t2.t2_col2 < 'd't2表中满足条件的仅是t2表中的第三行记录,因此将t1表中的第一行记录与t2表中的第三行记录匹配,结果如下:

    t1_col1 t1_col2 t2_col1 t2_col2
    3 c 3 c

    将两次查询的结果全部放到结果集中,例子中的连接查询的结果如下:image.png注意:

    • 要理解驱动表和被驱动表这组概念;
    • 在两表的连接查询中,驱动表仅查询一次,被驱动表查询多次,被驱动表查询的次数等于在驱动表查询的结果集里记录的数目。

      2、内连接和外连接

      2.1 内连接和外连接的概念

    • 内连接:驱动表中的记录在被驱动表中找不到匹配记录时,该记录不添加到结果集;

    • 外连接:驱动表中的记录在被驱动表中找不到匹配记录时,该记录仍要添加到结果集。

    在连接查询中会涉及到过滤条件,连接查询中过滤条件有两种:**WHERE**子句**ON**子句

    • **WHERE**子句
      • 就是前面介绍过的带搜索条件的查询时用的WHERE子句,WHERE子句针对的是记录;
    • **ON**子句
      • 当外连接的驱动表里的记录根据ON子句的过滤条件无法在被驱动表中找到匹配记录时,该记录仍然会加入到结果集,对应的被驱动表中的各个字段用NULL填充;
      • 内连接中的WHERE子句和ON子句是等价的。

    一般把只涉及单表的过滤条件放到**WHERE**子句中,把涉及两表的过滤条件都放到**ON**子句中,一般把放到**ON**子句中的过滤条件称之为连接条件。

    2.2 内连接

    格式:

    1. SELECT * FROM t1 [INNER | CROSS] JOIN t2 [ON 连接条件] [WHERE 普通过滤条件];

    一般推荐这种写法:

    1. SELECT * FROM t1 INNER JOIN t2 WHERE 普通过滤条件;

    内连接中驱动表和被驱动表的位置互换后不影响最终结果,因为内连接是把不匹配的记录直接丢弃。

    2.3 外连接

    MySQL中外连接还可以细分成两种:左外连接右外连接,左外连接是选取左侧的表为驱动表,右外连接是选取右侧的表为驱动表。因为外连接中驱动表中的记录根据ON子句的连接条件不匹配时,被驱动表中对应的列的位置会被NULL填充,因此谁做被驱动表决定了最终的结果集,所以外连接要细分为左外连接和右外连接。

    2.3.1 左连接

    格式:

    1. SELECT * FROM t1 LEFT [OUTER] JOIN t2 ON 连接条件 [WHERE 普通过滤条件];
    • 左连接里,放在左边的表是外表或者驱动表,放在右边的表是内标或者被驱动表;

    举例

    1. SELECT student_info.number, name, major, subject, score FROM student_info LEFT JOIN student_score ON student_info.number = student_score.number;

    2.3.2 右连接

    格式:

    1. SELECT * FROM t1 RIGHT [OUTER] JOIN t2 ON 连接条件 [WHERE 普通过滤条件];
    • 右连接里,驱动表在右边,被驱动表在左边;

      3、自连接

      3.1 表的别名

      列可以通过AS获得列的别名,表也可以通过AS指定表的别名,举例:
      1. SELECT s1.number, s1.name, s1.major, s2.subject, s2.score FROM student_info AS s1 INNER JOIN student_score AS s2 WHERE s1.number = s2.number;
      格式是在FROM后面的真实表名后面,通过AS再指定表的别名。通过上面的SQL语句,查询学生信息表和学生成绩表中共同学号的学生的信息。

      3.2 自连接

    上面介绍的连接查询都是多个不同的表连接,同一张表也可以进行连接查询,称为自连接。自连接里相当于对表建立一个副本,并对副本建立一个表的别名。举个例子,想在学生信息表中,查看与“史珍香”同学相同专业的学生信息,可以使用自连接,SQL语句如下:

    1. SELECT s2.student_number, s2.name, s2.major FROM student_info AS s2 INNER JOIN student_info AS s1 WHERE s2.major=s1.major AND s1.name='史珍香';

    结果:image.png

    4、连接查询多张表时如何选择驱动表

    参考

    Mysql多表连接查询的执行细节(一)

    评论:0   参与:  13