Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL连接查询

MySQL数据库连接查询 join原理

作者:彭世瑜

这篇文章主要介绍了MySQL数据库连接查询 join原理,文章首先通过将多张表连到一起查询 导致记录行数和字段列发生变化,利用一对一、一对多和多对多关系保证数据完整性展开主题内容,需要的小伙伴可以参考一下

1、连接查询的分类

2、交叉连接

将两张表的数据与另外一张表彼此交叉

2.1、原理

笛卡尔积:

2.2、基本语法

表1 cross join 表2;
mysql> select * from tb_teacher;
+--------+------+
| name   | age  |
+--------+------+
| Jack   |   24 |
| Tom    |   26 |
| Steve  | NULL |
| 张三   |   23 |
| 张三   |   23 |
+--------+------+
5 rows in set (0.00 sec)

mysql> select * from my_student;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  7 | 张飞   |        2 |   21 |      1 |
|  8 | 关羽   |        1 |   22 |      2 |
|  9 | 曹操   |        1 |   20 |   NULL |
+----+--------+----------+------+--------+
6 rows in set (0.01 sec)

mysql> select * from my_student cross join tb_teacher;
+----+--------+----------+------+--------+--------+------+
| id | name   | class_id | age  | gender | name   | age  |
+----+--------+----------+------+--------+--------+------+
|  1 | 刘备   |        1 |   18 |      2 | Jack   |   24 |
|  1 | 刘备   |        1 |   18 |      2 | Tom    |   26 |
|  1 | 刘备   |        1 |   18 |      2 | Steve  | NULL |
|  1 | 刘备   |        1 |   18 |      2 | 张三   |   23 |
|  1 | 刘备   |        1 |   18 |      2 | 张三   |   23 |
|  2 | 李四   |        1 |   19 |      1 | Jack   |   24 |
|  2 | 李四   |        1 |   19 |      1 | Tom    |   26 |
|  2 | 李四   |        1 |   19 |      1 | Steve  | NULL |
|  2 | 李四   |        1 |   19 |      1 | 张三   |   23 |
|  2 | 李四   |        1 |   19 |      1 | 张三   |   23 |
|  3 | 王五   |        2 |   20 |      2 | Jack   |   24 |
|  3 | 王五   |        2 |   20 |      2 | Tom    |   26 |
|  3 | 王五   |        2 |   20 |      2 | Steve  | NULL |
|  3 | 王五   |        2 |   20 |      2 | 张三   |   23 |
|  3 | 王五   |        2 |   20 |      2 | 张三   |   23 |
|  7 | 张飞   |        2 |   21 |      1 | Jack   |   24 |
|  7 | 张飞   |        2 |   21 |      1 | Tom    |   26 |
|  7 | 张飞   |        2 |   21 |      1 | Steve  | NULL |
|  7 | 张飞   |        2 |   21 |      1 | 张三   |   23 |
|  7 | 张飞   |        2 |   21 |      1 | 张三   |   23 |
|  8 | 关羽   |        1 |   22 |      2 | Jack   |   24 |
|  8 | 关羽   |        1 |   22 |      2 | Tom    |   26 |
|  8 | 关羽   |        1 |   22 |      2 | Steve  | NULL |
|  8 | 关羽   |        1 |   22 |      2 | 张三   |   23 |
|  8 | 关羽   |        1 |   22 |      2 | 张三   |   23 |
|  9 | 曹操   |        1 |   20 |   NULL | Jack   |   24 |
|  9 | 曹操   |        1 |   20 |   NULL | Tom    |   26 |
|  9 | 曹操   |        1 |   20 |   NULL | Steve  | NULL |
|  9 | 曹操   |        1 |   20 |   NULL | 张三   |   23 |
|  9 | 曹操   |        1 |   20 |   NULL | 张三   |   23 |
+----+--------+----------+------+--------+--------+------+
30 rows in set (0.00 sec)

2.3、应用

基本没有实际意义

等价于

select * from my_student, tb_teacher;

3、内连接

从一张表中取出所有的记录,去另外一张表中匹配,利用匹配条件进行匹配,成功则保留,失败则放弃

3.1、原理

3.2、基本语法

表1 inner join 表2 on 匹配条件
create table my_class(
    id int primary key auto_increment,
    name varchar(10) not null
);

insert into my_class (name) values ('一班'), ('二班');

mysql> select * from my_class;
+----+--------+
| id | name   |
+----+--------+
|  1 | 一班   |
|  2 | 二班   |
+----+--------+

mysql> select * from my_student;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  4 | 张飞   |        2 |   21 |      1 |
|  5 | 关羽   |        1 |   22 |      2 |
|  6 | 曹操   |        1 |   20 |   NULL |
+----+--------+----------+------+--------+

-- 如果内连接没有条件,其实就是交叉连接(笛卡尔积)
mysql> select * from my_student inner join my_class;
+----+--------+----------+------+--------+----+--------+
| id | name   | class_id | age  | gender | id | name   |
+----+--------+----------+------+--------+----+--------+
|  1 | 刘备   |        1 |   18 |      2 |  1 | 一班   |
|  1 | 刘备   |        1 |   18 |      2 |  2 | 二班   |
|  2 | 李四   |        1 |   19 |      1 |  1 | 一班   |
|  2 | 李四   |        1 |   19 |      1 |  2 | 二班   |
|  3 | 王五   |        2 |   20 |      2 |  1 | 一班   |
|  3 | 王五   |        2 |   20 |      2 |  2 | 二班   |
|  4 | 张飞   |        2 |   21 |      1 |  1 | 一班   |
|  4 | 张飞   |        2 |   21 |      1 |  2 | 二班   |
|  5 | 关羽   |        1 |   22 |      2 |  1 | 一班   |
|  5 | 关羽   |        1 |   22 |      2 |  2 | 二班   |
|  6 | 曹操   |        1 |   20 |   NULL |  1 | 一班   |
|  6 | 曹操   |        1 |   20 |   NULL |  2 | 二班   |
+----+--------+----------+------+--------+----+--------+
12 rows in set (0.00 sec)

-- 表的设计,通常会有同名字段,通常使用`表名.字段`来保证唯一性
mysql> select * from my_student inner join my_class on my_student.class_id = my_class.id;
+----+--------+----------+------+--------+----+--------+
| id | name   | class_id | age  | gender | id | name   |
+----+--------+----------+------+--------+----+--------+
|  1 | 刘备   |        1 |   18 |      2 |  1 | 一班   |
|  2 | 李四   |        1 |   19 |      1 |  1 | 一班   |
|  3 | 王五   |        2 |   20 |      2 |  2 | 二班   |
|  4 | 张飞   |        2 |   21 |      1 |  2 | 二班   |
|  5 | 关羽   |        1 |   22 |      2 |  1 | 一班   |
|  6 | 曹操   |        1 |   20 |   NULL |  1 | 一班   |
+----+--------+----------+------+--------+----+--------+

-- 如果表名比较长,可以使用别名简化
mysql> select * from my_student as a inner join my_class b on a.class_id = b.id;
+----+--------+----------+------+--------+----+--------+
| id | name   | class_id | age  | gender | id | name   |
+----+--------+----------+------+--------+----+--------+
|  1 | 刘备   |        1 |   18 |      2 |  1 | 一班   |
|  2 | 李四   |        1 |   19 |      1 |  1 | 一班   |
|  3 | 王五   |        2 |   20 |      2 |  2 | 二班   |
|  4 | 张飞   |        2 |   21 |      1 |  2 | 二班   |
|  5 | 关羽   |        1 |   22 |      2 |  1 | 一班   |
|  6 | 曹操   |        1 |   20 |   NULL |  1 | 一班   |
+----+--------+----------+------+--------+----+--------+

-- 可以交换两张表的先后顺序
mysql> select * from my_class b inner join my_student as a on a.class_id = b.id;
+----+--------+----+--------+----------+------+--------+
| id | name   | id | name   | class_id | age  | gender |
+----+--------+----+--------+----------+------+--------+
|  1 | 一班   |  1 | 刘备   |        1 |   18 |      2 |
|  1 | 一班   |  2 | 李四   |        1 |   19 |      1 |
|  2 | 二班   |  3 | 王五   |        2 |   20 |      2 |
|  2 | 二班   |  4 | 张飞   |        2 |   21 |      1 |
|  1 | 一班   |  5 | 关羽   |        1 |   22 |      2 |
|  1 | 一班   |  6 | 曹操   |        1 |   20 |   NULL |
+----+--------+----+--------+----------+------+--------+

-- on 可以使用 where 替换,推荐使用 on
mysql> select * from my_class b inner join my_student as a where a.class_id = b.id;
+----+--------+----+--------+----------+------+--------+
| id | name   | id | name   | class_id | age  | gender |
+----+--------+----+--------+----------+------+--------+
|  1 | 一班   |  1 | 刘备   |        1 |   18 |      2 |
|  1 | 一班   |  2 | 李四   |        1 |   19 |      1 |
|  2 | 二班   |  3 | 王五   |        2 |   20 |      2 |
|  2 | 二班   |  4 | 张飞   |        2 |   21 |      1 |
|  1 | 一班   |  5 | 关羽   |        1 |   22 |      2 |
|  1 | 一班   |  6 | 曹操   |        1 |   20 |   NULL |
+----+--------+----+--------+----------+------+--------+

3.3、应用

内连接通常是在对数据有精确要求的地方使用,必须保证两张表中都能进行数据匹配,内连接匹配到才会保存

4、外连接

按照某一张表作为主表(表中所有记录在最后都会保留)根据条件取连接另外一张表,从而得到目标数据

外连接分为两种:

4.1、原理

4.2、基本语法

-- 左连接
主表 left join 从表 on 连接条件;
-- 右连接
从表 right join 主表 on 连接条件;

左表的数据在前,右表的数据在后

mysql> select * from my_student;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  4 | 张飞   |        2 |   21 |      1 |
|  5 | 关羽   |        1 |   22 |      2 |
|  6 | 曹操   |        1 |   20 |   NULL |
+----+--------+----------+------+--------+
mysql> select * from my_class;
+----+--------+
| id | name   |
+----+--------+
|  1 | 一班   |
|  3 | 三班   |
|  2 | 二班   |
+----+--------+
mysql> select * from my_student as s left join my_class c on s.class_id = c.id;
+----+--------+----------+------+--------+------+--------+
| id | name   | class_id | age  | gender | id   | name   |
+----+--------+----------+------+--------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |    1 | 一班   |
|  2 | 李四   |        1 |   19 |      1 |    1 | 一班   |
|  3 | 王五   |        2 |   20 |      2 |    2 | 二班   |
|  4 | 张飞   |        2 |   21 |      1 |    2 | 二班   |
|  5 | 关羽   |        1 |   22 |      2 |    1 | 一班   |
|  6 | 曹操   |        1 |   20 |   NULL |    1 | 一班   |
+----+--------+----------+------+--------+------+--------+
select * from my_student as s right join my_class c on s.class_id = c.id;
mysql> select * from my_student as s right join my_class c on s.class_id = c.id;
+------+--------+----------+------+--------+----+--------+
| id   | name   | class_id | age  | gender | id | name   |
+------+--------+----------+------+--------+----+--------+
|    1 | 刘备   |        1 |   18 |      2 |  1 | 一班   |
|    2 | 李四   |        1 |   19 |      1 |  1 | 一班   |
|    3 | 王五   |        2 |   20 |      2 |  2 | 二班   |
|    4 | 张飞   |        2 |   21 |      1 |  2 | 二班   |
|    5 | 关羽   |        1 |   22 |      2 |  1 | 一班   |
|    6 | 曹操   |        1 |   20 |   NULL |  1 | 一班   |
| NULL | NULL   |     NULL | NULL |   NULL |  3 | 三班   |
+------+--------+----------+------+--------+----+--------+

4.3、特点

外连接中主表的数据一定会保存,连接之后不会出现记录数少于主表(内连接可能少数据)

左连接和右连接可以相互转换,但是数据对应的位置(字段顺序)会改变

4.4、应用

获取对应主表以及其他数据(关联)

通常使用左连接

5、using关键字

在连接查询中用来代替对应on关键字进行条件匹配

5.1、原理

5.2、基本语法

表1 [inner, left, right] join 表2 using (同名字段列表);
select * from my_student left join my_class using(class_id);
-- 等价于
select * from my_student left join my_class on my_student.class_id = my_class.class_id;

这个方法通常不使用

到此这篇关于MySQL数据库连接查询 join原理的文章就介绍到这了,更多相关MySQL连接查询内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文