MySQL中的连接查询

连接查询

  • 连接查询:将多张表(大于等于 2 张表)按照某个指定的条件进行数据的拼接,其最终结果记录数可能有变化,但字段数一定会增加。
  • 意义:在用户查询数据的时候,需要显示的数据来自多张表。
  • 连接查询的语法格式:左表 join 右表
  • 连接查询的分类
    • 内连接
    • 外连接
    • 自然连接
    • 交叉连接

交叉连接

  • 交叉连接:cross join,从一张表中循环取出每一条记录,每条记录都去另外一张表进行匹配,匹配的结果都保留(没有条件匹配),而连接本身的字段会增加,最终形成的结果为笛卡尔积形式。实际上,笛卡尔积形式(交叉连接和多表查询)的结果并没有什么实际意义,应该尽量避免,其存在的价值就是保证连接这种结构的完整性
  • 基本语法:左表 cross join 右表,效果与多表查询相同!
    mysql> SELECT * FROM student cross join class;
    +----+--------+------+-------+------+------+----+-------+------+
    | id | name   | age  | grade | sex  | c_id | id | grade | room |
    +----+--------+------+-------+------+------+----+-------+------+
    |  1 | curry  |   30 |   3.1 | 男   |    1 |  1 |   3.1 | A    |
    |  1 | curry  |   30 |   3.1 | 男   |    1 |  2 |   3.2 | B    |
    |  1 | curry  |   30 |   3.1 | 男   |    1 |  3 |   3.4 | C    |
    |  2 | durant |   29 |   3.4 | 男   |    1 |  1 |   3.1 | A    |
    |  2 | durant |   29 |   3.4 | 男   |    1 |  2 |   3.2 | B    |
    |  2 | durant |   29 |   3.4 | 男   |    1 |  3 |   3.4 | C    |
    |  3 | Riuo   |   27 |   3.6 | 女   |    1 |  1 |   3.1 | A    |
    |  3 | Riuo   |   27 |   3.6 | 女   |    1 |  2 |   3.2 | B    |
    |  3 | Riuo   |   27 |   3.6 | 女   |    1 |  3 |   3.4 | C    |
    |  4 | harden |   29 |   3.2 | 男   |    1 |  1 |   3.1 | A    |
    |  4 | harden |   29 |   3.2 | 男   |    1 |  2 |   3.2 | B    |
    |  4 | harden |   29 |   3.2 | 男   |    1 |  3 |   3.4 | C    |
    +----+--------+------+-------+------+------+----+-------+------+
    12 rows in set (0.16 sec)
    
    mysql> SELECT * FROM student, class;
    +----+--------+------+-------+------+------+----+-------+------+
    | id | name   | age  | grade | sex  | c_id | id | grade | room |
    +----+--------+------+-------+------+------+----+-------+------+
    |  1 | curry  |   30 |   3.1 | 男   |    1 |  1 |   3.1 | A    |
    |  1 | curry  |   30 |   3.1 | 男   |    1 |  2 |   3.2 | B    |
    |  1 | curry  |   30 |   3.1 | 男   |    1 |  3 |   3.4 | C    |
    |  2 | durant |   29 |   3.4 | 男   |    1 |  1 |   3.1 | A    |
    |  2 | durant |   29 |   3.4 | 男   |    1 |  2 |   3.2 | B    |
    |  2 | durant |   29 |   3.4 | 男   |    1 |  3 |   3.4 | C    |
    |  3 | Riuo   |   27 |   3.6 | 女   |    1 |  1 |   3.1 | A    |
    |  3 | Riuo   |   27 |   3.6 | 女   |    1 |  2 |   3.2 | B    |
    |  3 | Riuo   |   27 |   3.6 | 女   |    1 |  3 |   3.4 | C    |
    |  4 | harden |   29 |   3.2 | 男   |    1 |  1 |   3.1 | A    |
    |  4 | harden |   29 |   3.2 | 男   |    1 |  2 |   3.2 | B    |
    |  4 | harden |   29 |   3.2 | 男   |    1 |  3 |   3.4 | C    |
    +----+--------+------+-------+------+------+----+-------+------+
    12 rows in set (0.00 sec)
    

内连接

  • 内连接:inner join,从左表中取出每一条记录,和右表中的所有记录进行匹配,并且仅当某个条件在左表和右表中的值相同时,结果才会保留,否则不保留
  • 基本语法:左表 + [inner] join + 右表 + on 左表.字段 = 右表.字段;其中,关键字on表示连接条件,两表中的条件字段有着相同的业务含义
  • 实例:将表student与表class进行内连接
    mysql> SELECT * FROM student join class
        -> on student.grade = class.grade;
    +----+--------+------+-------+------+------+----+-------+------+
    | id | name   | age  | grade | sex  | c_id | id | grade | room |
    +----+--------+------+-------+------+------+----+-------+------+
    |  1 | curry  |   30 |   3.1 | 男   |    1 |  1 |   3.1 | A    |
    |  2 | durant |   29 |   3.4 | 男   |    1 |  3 |   3.4 | C    |
    |  4 | harden |   29 |   3.2 | 男   |    1 |  2 |   3.2 | B    |
    +----+--------+------+-------+------+------+----+-------+------+
    3 rows in set (0.00 sec)
    
  • 注意:如果两表中有某张表的条件字段名唯一,那么在书写连接条件的时候,可以省略表名,直接书写字段名。MySQL 会自动识别唯一字段名,但不建议这么做。此外,在上面的结果中有同名字段,这会给我们理解数据的意义造成一定的困扰,这时就需要使用字段别名和表别名做区别啦!
  • 实例:将表student与表class进行内连接,起别名
    mysql> SELECT s.*, c.id as class_id, c.grade as c_grade,room
        -> from student as s
        -> inner join class as c
        -> on s.grade = c.grade;
    +----+--------+------+-------+------+------+----------+---------+------+
    | id | name   | age  | grade | sex  | c_id | class_id | c_grade | room |
    +----+--------+------+-------+------+------+----------+---------+------+
    |  1 | curry  |   30 |   3.1 | 男   |    1 |        1 |     3.1 | A    |
    |  2 | durant |   29 |   3.4 | 男   |    1 |        3 |     3.4 | C    |
    |  4 | harden |   29 |   3.2 | 男   |    1 |        2 |     3.2 | B    |
    +----+--------+------+-------+------+------+----------+---------+------+
    3 rows in set (0.00 sec)
    
  • 最后,内连接可以没有连接条件:可以没有on及之后的内容,这时内连接的结果全部保留,与交叉连接的结果完全相同。而且在内连接的时候可以使用where关键字代替on,但不建议这么做,因为where没有on的效率高。

外连接

  • 外连接:left\right join,以某张表为主表,取出里面的所有记录,然后让主表中的每条记录都与另外一张表进行连接。不管能否匹配成功,其最终结果都会保留,匹配成功,则正确保留;匹配失败,则将另外一张表的字段都置为NULL。
  • 基本语法:左表 + left\right + join + 右表 + on + 左表.字段 = 右表.字段;其中,关键字on表示连接条件,两表中的条件字段有着相同的业务含义。在这里,以主表为依据,外连接分为两种,分别为:
    • left join:左外连接(左连接),以左表为主表;
    • right join: 右外连接(右连接),以右表为主表;
  • 实例:将表 student 与 class 进行左连接
    mysql> SELECT s.*, c_id as class_id, c.grade as c_grade, room
        -> FROM student as s
        -> left join class as c
        -> on s.grade = c.grade;
    +----+--------+------+-------+------+------+----------+---------+------+
    | id | name   | age  | grade | sex  | c_id | class_id | c_grade | room |
    +----+--------+------+-------+------+------+----------+---------+------+
    |  1 | curry  |   30 |   3.1 | 男   |    1 |        1 |     3.1 | A    |
    |  4 | harden |   29 |   3.2 | 男   |    1 |        1 |     3.2 | B    |
    |  2 | durant |   29 |   3.4 | 男   |    1 |        1 |     3.4 | C    |
    |  3 | Riuo   |   27 |   3.6 | 女   |    1 |        1 |    NULL | NULL |
    +----+--------+------+-------+------+------+----------+---------+------+
    4 rows in set (0.03 sec)
    
  • 无论以那张表为主表,其外连接的结果(记录数量)都不会少于主表的记录总数。此外,虽然左连接与右连接有主表差异,但显示的结果都是:左表的数据在左边,右表的数据在右边

自然连接

  • 自然连接:nature join,自然连接其实就是自动匹配连接条件,系统以两表中同名字段作为匹配条件,如果两表有多个同名字段,那就都作为匹配条件。在这里,自然连接可以分为自然内连接和自然外连接。
  • 1.自然内连接语法:左表 + natural + join + 右表;
  • 实例:将表 student 与 class 进行自然内连接
    mysql> SELECT * from student natural join class;
    +----+-------+-------+------+------+------+------+
    | id | grade | name  | age  | sex  | c_id | room |
    +----+-------+-------+------+------+------+------+
    |  1 |   3.1 | curry |   30 | 男   |    1 | A    |
    +----+-------+-------+------+------+------+------+
    1 row in set (0.00 sec)
    
  • 实例:将表 student 与 class 进行内连接,连接条件为 id 和 grade
    mysql> SELECT * from
        -> student inner join class
        -> on
        -> student.id = class.id and student.grade = class.grade;
    +----+-------+------+-------+------+------+----+-------+------+
    | id | name  | age  | grade | sex  | c_id | id | grade | room |
    +----+-------+------+-------+------+------+----+-------+------+
    |  1 | curry |   30 |   3.1 | 男   |    1 |  1 |   3.1 | A    |
    +----+-------+------+-------+------+------+----+-------+------+
    1 row in set (0.00 sec)
    
  • 自然连接自动使用同名字段作为连接条件,而且在连接完成之后合并同名字段
  • 2.自然外连接语法:左表 + natural + left/right + join + 右表;
  • 实例:将表 student 与 class 进行自然左外连接
    mysql> SELECT * FROM
        -> student natural left join class;
    +----+-------+--------+------+------+------+------+
    | id | grade | name   | age  | sex  | c_id | room |
    +----+-------+--------+------+------+------+------+
    |  1 |   3.1 | curry  |   30 | 男   |    1 | A    |
    |  2 |   3.4 | durant |   29 | 男   |    1 | NULL |
    |  3 |   3.6 | Riuo   |   27 | 女   |    1 | NULL |
    |  4 |   3.2 | harden |   29 | 男   |    1 | NULL |
    +----+-------+--------+------+------+------+------+
    4 rows in set (0.00 sec)
    
  • 实例:将表 student 与 class 进行自然右外连接
    mysql> SELECT * FROM
        -> student natural right join class;
    +----+-------+------+-------+------+------+------+
    | id | grade | room | name  | age  | sex  | c_id |
    +----+-------+------+-------+------+------+------+
    |  1 |   3.1 | A    | curry |   30 | 男   |    1 |
    |  2 |   3.2 | B    | NULL  | NULL | NULL | NULL |
    |  3 |   3.4 | C    | NULL  | NULL | NULL | NULL |
    +----+-------+------+-------+------+------+------+
    3 rows in set (0.00 sec)
    
  • 可以用内连接和外连接来模拟自然连接,模拟的关键就在于使用同名字段作为连接条件及合并同名字段
  • 基本语法:左表 + inner/left/right + join + 右表 + using(字段名);其中,using内部的字段名就是作为连接条件的字段,也是需要合并的同名字段。
  • 将表 student 与 class 进行自然左外连接/
    mysql> SELECT * FROM student natural left join class;
    +----+-------+--------+------+------+------+------+
    | id | grade | name   | age  | sex  | c_id | room |
    +----+-------+--------+------+------+------+------+
    |  1 |   3.1 | curry  |   30 | 男   |    1 | A    |
    |  2 |   3.4 | durant |   29 | 男   |    1 | NULL |
    |  3 |   3.6 | Riuo   |   27 | 女   |    1 | NULL |
    |  4 |   3.2 | harden |   29 | 男   |    1 | NULL |
    +----+-------+--------+------+------+------+------+
    4 rows in set (0.00 sec)
    -- 用左外连接模拟自然左外连接
    mysql> SELECT * FROM student left join class using(id, grade);
    +----+-------+--------+------+------+------+------+
    | id | grade | name   | age  | sex  | c_id | room |
    +----+-------+--------+------+------+------+------+
    |  1 |   3.1 | curry  |   30 | 男   |    1 | A    |
    |  2 |   3.4 | durant |   29 | 男   |    1 | NULL |
    |  3 |   3.6 | Riuo   |   27 | 女   |    1 | NULL |
    |  4 |   3.2 | harden |   29 | 男   |    1 | NULL |
    +----+-------+--------+------+------+------+------+
    4 rows in set (0.06 sec)
    

你可能感兴趣的:(MySQL中的连接查询)