MySQL表的内连和外连

目录

表的内连和外连

表的连接分为内连接和外连接

内连接

内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,我们前面学习的查询都是内连接,也是在开发过程中使用的最多的连接查询。

通俗解释 :内连接就像一次"严格匹配"的相亲大会。只把双方都符合条件(有共同department_id) 的信息配对成功并展示出来如果有人没有对象 (比如赵六的department_id是NULL),或者有对象但对方没来 (比如市场部在员工表里没人),那他们就不会出现在结果里

语法:

复制代码
select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件;

inner join 可以简写成 join,因为MySQL默认就是内连接。

备注:前面学习的都是内连接

案例:显示SMITH的名字和部门名称

c 复制代码
-- 用前面的写法
mysql> select ename,dname from emp,dept where emp.deptno = dept.deptno and ename = 'SMITH';
+-------+----------+
| ename | dname    |
+-------+----------+
| SMITH | RESEARCH |
+-------+----------+
1 row in set (0.00 sec)

-- 用标准的内连接写法
mysql> select ename,dname from emp inner join dept on emp.deptno=dept.deptno and ename='SMITH';
+-------+----------+
| ename | dname    |
+-------+----------+
| SMITH | RESEARCH |
+-------+----------+
1 row in set (0.00 sec)

使用场景:当你只想获取在两个表中都有对应关系的数据时,就用内连接。

  • 查询订单和客户信息(只查看已下单的客户)。
  • 查询学生和选课信息(只查看有学生选的课程)。
  • 查询文章和评论(只查看有评论的文章)。

外连接

外连接分为左外连接、右外连接和全外连接。MySQL不支持全外连接,所以我们重点讲前两个。

左外连接

如果联合查询,左侧的表完全显示我们就说是左外连接。

左外连接 - "以左表为绝对核心"
通俗解释:左连接就像公司的人力资源部做全员统计。左边的员工表是核心,一个都不能少。不管员工有没有部门(department_id是否为空),都要出现在名单上。然后,再去右边的部门表里找匹配的部门名称,如果找不到,就用NULL填充。

语法:

复制代码
select 字段名 from 表名1 left join 表名2 on 连接条件

案例:

c 复制代码
--- 创建两张表
mysql> create table stu( id int, name varchar(30));
Query OK, 0 rows affected (0.02 sec)

mysql> create table exam(
    -> id int,
    -> grade int);
Query OK, 0 rows affected (0.02 sec)

mysql> insert into stu values (1,'Jon'),(2,'Tom'),(4,'Lisa'),(5,'Lili');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> insert into exam values(1,12),(2,34),(11,9);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from stu;
+------+------+
| id   | name |
+------+------+
|    1 | Jon  |
|    2 | Tom  |
|    4 | Lisa |
|    5 | Lili |
+------+------+
4 rows in set (0.00 sec)

mysql> select * from exam;
+------+-------+
| id   | grade |
+------+-------+
|    1 |    12 |
|    2 |    34 |
|   11 |     9 |
+------+-------+
3 rows in set (0.00 sec)
  • 查询所有学生的成绩,如果这个学生没有成绩,也要将学生的个人信息显示出来
c 复制代码
-- 左外连接:当左边表和右边表没有匹配时,也会显示左边表的数据
mysql> select * from stu left join exam on stu.id=exam.id;
+------+------+------+-------+
| id   | name | id   | grade |
+------+------+------+-------+
|    1 | Jon  |    1 |    12 |
|    2 | Tom  |    2 |    34 |
|    4 | Lisa | NULL |  NULL |
|    5 | Lili | NULL |  NULL |
+------+------+------+-------+
4 rows in set (0.00 sec)
--- 内连接:只显示匹配数据
mysql> select * from stu inner join exam on stu.id=exam.id;
+------+------+------+-------+
| id   | name | id   | grade |
+------+------+------+-------+
|    1 | Jon  |    1 |    12 |
|    2 | Tom  |    2 |    34 |
+------+------+------+-------+
2 rows in set (0.00 sec)

使用场景:当你需要获取左表的全部记录,以及右表中与之匹配的记录时。

  • 统计每个客户的订单量(包括没下过单的客户)。
  • 查找所有员工的信息,包括尚未分配部门的员工(如上例)。
  • 计算每个产品的销售总额,包括一件都没卖出去的产品。

右外连接

如果联合查询,右侧的表完全显示我们就说是右外连接。

右外连接 - "以右表为绝对核心"
通俗解释:右连接和左连接完全相反。它以右边的表为核心,一个都不能少。然后去左边的表里找匹配项,找不到就用NULL填充。在实际开发中,右连接用得较少,因为我们可以通过调整表的顺序,用左连接来实现同样的效果,这样代码更统一,更易读。

语法:

复制代码
select 字段 from 表名1 right join 表名2 on 连接条件;

案例:

  • 对stu表和exam表联合查询,把所有的成绩都显示出来,即使这个成绩没有学生与它对应,也要显示出来
c 复制代码
mysql> select * from stu right join exam on stu.id=exam.id;
+------+------+------+-------+
| id   | name | id   | grade |
+------+------+------+-------+
|    1 | Jon  |    1 |    12 |
|    2 | Tom  |    2 |    34 |
| NULL | NULL |   11 |     9 |
+------+------+------+-------+
3 rows in set (0.00 sec)

练习:

  • 列出部门名称和这些部门的员工信息,同时列出没有员工的部门
c 复制代码
--- 方法1:使用左外连接
mysql> select dept.deptno,dept.dname,empno,ename,job from dept left join emp on dept.deptno=emp.deptno;
+--------+------------+--------+--------+-----------+
| deptno | dname      | empno  | ename  | job       |
+--------+------------+--------+--------+-----------+
|     10 | ACCOUNTING | 007934 | MILLER | CLERK     |
|     10 | ACCOUNTING | 007839 | KING   | PRESIDENT |
|     10 | ACCOUNTING | 007782 | CLARK  | MANAGER   |
|     20 | RESEARCH   | 007902 | FORD   | ANALYST   |
|     20 | RESEARCH   | 007876 | ADAMS  | CLERK     |
|     20 | RESEARCH   | 007788 | SCOTT  | ANALYST   |
|     20 | RESEARCH   | 007566 | JONES  | MANAGER   |
|     20 | RESEARCH   | 007369 | SMITH  | CLERK     |
|     30 | SALES      | 007900 | JAMES  | CLERK     |
|     30 | SALES      | 007844 | TURNER | SALESMAN  |
|     30 | SALES      | 007698 | BLAKE  | MANAGER   |
|     30 | SALES      | 007654 | MARTIN | SALESMAN  |
|     30 | SALES      | 007521 | WARD   | SALESMAN  |
|     30 | SALES      | 007499 | ALLEN  | SALESMAN  |
|     40 | OPERATIONS |   NULL | NULL   | NULL      |
+--------+------------+--------+--------+-----------+
15 rows in set (0.00 sec)

这个查询和上面的右连接查询结果完全一样。所以,掌握左连接就足够了。

c 复制代码
--- 方法2:使用右外连接
mysql> select dept.deptno,dept.dname,empno,ename,job from emp right join dept on dept.deptno=emp.deptno;
+--------+------------+--------+--------+-----------+
| deptno | dname      | empno  | ename  | job       |
+--------+------------+--------+--------+-----------+
|     10 | ACCOUNTING | 007934 | MILLER | CLERK     |
|     10 | ACCOUNTING | 007839 | KING   | PRESIDENT |
|     10 | ACCOUNTING | 007782 | CLARK  | MANAGER   |
|     20 | RESEARCH   | 007902 | FORD   | ANALYST   |
|     20 | RESEARCH   | 007876 | ADAMS  | CLERK     |
|     20 | RESEARCH   | 007788 | SCOTT  | ANALYST   |
|     20 | RESEARCH   | 007566 | JONES  | MANAGER   |
|     20 | RESEARCH   | 007369 | SMITH  | CLERK     |
|     30 | SALES      | 007900 | JAMES  | CLERK     |
|     30 | SALES      | 007844 | TURNER | SALESMAN  |
|     30 | SALES      | 007698 | BLAKE  | MANAGER   |
|     30 | SALES      | 007654 | MARTIN | SALESMAN  |
|     30 | SALES      | 007521 | WARD   | SALESMAN  |
|     30 | SALES      | 007499 | ALLEN  | SALESMAN  |
|     40 | OPERATIONS |   NULL | NULL   | NULL      |
+--------+------------+--------+--------+-----------+
15 rows in set (0.00 sec)
--- 可以使用别名
mysql> select d.deptno,d.dname,e.empno,e.ename,e.job from emp e right join dept d on d.deptno=e.deptno;

一句话记忆:

内连接:求交集,严格匹配。

左连接:保左全,右填空。

右连接:保右全,左填空(但通常用"调换表顺序的左连接"来代替)。

相关推荐
dora2 小时前
Flutter中dart和原生代码的通信之MethodChannel
android·flutter
路上^_^2 小时前
安卓基础组件031-Retrofit 网络请求框架
android
jingfeng5143 小时前
MySQL库的操作(ubuntu)
数据库·mysql
独行soc8 小时前
2025年渗透测试面试题总结-97(题目+回答)
网络·安全·web安全·adb·面试·渗透测试·安全狮
计算机毕业设计小帅8 小时前
【2026计算机毕业设计】基于Springboot的Android校园周边美食汇系统
android·spring boot·课程设计
每次的天空8 小时前
Android-MVX技术总结
android
叱咤少帅(少帅)10 小时前
DML语句
mysql
编码追梦人11 小时前
探索 Docker/K8s 部署 MySQL 的创新实践与优化技巧
mysql·docker·kubernetes
Digitally12 小时前
如何备份和恢复安卓设备2025
android