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;

一句话记忆:

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

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

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

相关推荐
程序员陆业聪4 小时前
从 OpenClaw 到 Android:Harness Engineering 是怎么让 Agent 变得可用的
android
身如柳絮随风扬5 小时前
MySQL核心知识
数据库·mysql
hnlgzb6 小时前
常见的Android Jetpack库会有哪些?这些库中又有哪些常用类的?
android·android jetpack
551只玄猫6 小时前
【数据库原理 实验报告1】创建和管理数据库
数据库·sql·学习·mysql·课程设计·实验报告·数据库原理
q5431470876 小时前
MySQL SQL100道基础练习题
数据库·mysql
zhoupenghui1687 小时前
mysql 中如果条件where中有or,则要求or两边的字段都必须有索引,否则不能用到索引, 为什么?
数据库·mysql·索引
eggwyw8 小时前
完美解决phpstudy安装后mysql无法启动
数据库·mysql
java修仙传8 小时前
MySQL 事务隔离级别详解
数据库·mysql·oracle
Irissgwe8 小时前
MySQL存储过程和触发器专题
数据库·mysql·oracle
钛态9 小时前
Flutter 三方库 http_mock_adapter — 赋能鸿蒙应用开发的高效率网络接口 Mock 与自动化测试注入引擎(适配鸿蒙 HarmonyOS Next ohos)
android·网络协议·flutter·http·华为·中间件·harmonyos