【MySQL】(8)内外连接

内连接

概念

内连接(Inner Join)是 SQL 查询中最常用的连接方式之一,它用于在两个或多个表之间根据共同的字段将数据进行合并。

内连接基于两个或多个表之间的共同列(也称为关联列)进行匹配,然后返回匹配行的组合。匹配的条件由 ON 子句指定。如果两个表中的行不匹配,则不会包含在内连接的结果集中。

上一节,我们在 from 后面跟多张表,然后使用 where 来筛选其实就是内连接

内连接之所以被称为内连接,是因为它只返回满足连接条件的行,而不包含不满足连接条件的行。也就是说,内连接只关心两个表格之间的共同部分,而忽略了不匹配的行。

内连接的另一个常见名称是等值连接(Equi-Join),因为内连接通常基于两个表格之间的等值关系进行匹配,即两个表格的关联列上的值相等。内连接还可以基于不等的关系进行匹配,如使用 <><=>=<> 等操作符,这样的连接称为不等值连接(Non-Equi-Join)。

inner join/join

在 SQL 中,还可以使用 INNER JOINJOIN 关键字来执行内连接。两个或多个表格可以通过 JOIN 关键字进行连接,使用 ON 子句指定连接条件

语法

SELECT column1, column2, ...
FROM table1
[INNER ]JOIN table2
ON table1.column_name = table2.column_name;

显示SMITH的名字和部门名称

-- from where 的写法
select ename, dname
from emp, dept
where emp.deptno = dept.deptno and ename = 'SMITH';

-- 标准的内连接写法
select ename, dname
from emp
inner join dept
on emp.deptno = dept.deptno
where ename = 'SMITH';

Q:使用 INNER JOIN 和使用 FROM WHERE 两种方式,哪个好呢?

A:使用 INNER JOIN 更加简洁明了,语法结构清晰,可以在 ON 子句中指定连接条件,易于阅读和维护。同时,使用 INNER JOIN 还可以避免笛卡尔积和重复数据等问题,提高查询效率和性能。

而使用 FROM 子句和 WHERE 子句的方式进行内连接,语法相对复杂,需要指定多个表格之间的连接条件,易于出现语法错误和逻辑错误,而且不能清晰地区分连接条件和筛选条件。在语句复杂度较高时,使用 INNER JOIN 可以更好地维护和优化 SQL 语句。

综上所述,INNER JOIN 更加简洁明了,易于阅读和维护,而且效率更高,建议使用 INNER JOIN 进行内连接。

外连接

与内连接不同,外连接可以包含左表、右表或两个表中所有的行,即使没有匹配的行也会包含在结果集中。外连接基于两个或多个表之间的共同列(也称为关联列)进行匹配,匹配的条件由 ON 子句指定。

在 MySQL 中,可以使用 LEFT JOINRIGHT JOIN 关键字来执行外连接。

左外连接

将两表称为左表和右表,左外连接相当于对两表先做内连接,然后将左表中未出现在内连接结果中的行补上去,其右表部分以 NULL 填充。

LEFT JOIN 用于进行左外连接

以下表为例

CREATE TABLE department (
  id INT PRIMARY KEY,
  name VARCHAR(50)
);

CREATE TABLE employee (
  id INT PRIMARY KEY,
  name VARCHAR(50),
  department_id INT,
  salary INT
);

INSERT INTO department (id, name) VALUES (1, 'Sales');
INSERT INTO department (id, name) VALUES (2, 'Marketing');
INSERT INTO department (id, name) VALUES (3, 'Finance');

INSERT INTO employee (id, name, department_id, salary) VALUES (1, 'John', 1, 50000);
INSERT INTO employee (id, name, department_id, salary) VALUES (2, 'Jane', 1, 55000);
INSERT INTO employee (id, name, department_id, salary) VALUES (3, 'Bob', 2, 60000);
INSERT INTO employee (id, name, department_id, salary) VALUES (4, 'Alice', 4, 70000);
INSERT INTO employee (id, name, department_id, salary) VALUES (5, 'Mark', NULL, 80000);
INSERT INTO employee (id, name, department_id, salary) VALUES (6, 'Emily', NULL, 90000);

select *
from employee
left join department
on employee.department_id = department.id;

上述查询以 employee 为左表,department 为右表,employee 中无法与 department 匹配的 id456 的三行也会显示到最终的查询结果中,右表部分会以 NULL 显示

查询结果:

+----+-------+---------------+--------+------+-----------+
| id | name  | department_id | salary | id   | name      |
+----+-------+---------------+--------+------+-----------+
|  1 | John  |             1 |  50000 |    1 | Sales     |
|  2 | Jane  |             1 |  55000 |    1 | Sales     |
|  3 | Bob   |             2 |  60000 |    2 | Marketing |
|  4 | Alice |             4 |  70000 | NULL | NULL      |
|  5 | Mark  |          NULL |  80000 | NULL | NULL      |
|  6 | Emily |          NULL |  90000 | NULL | NULL      |
+----+-------+---------------+--------+------+-----------+
6 rows in set (0.00 sec)

右外连接

将两表称为左表和右表,右外连接相当于对两表先做内连接,然后将右表中未出现在内连接结果中的行补上去,其左表部分以 NULL 填充。

RIGHT JOIN 用于进行右外连接

select *
from employee
right join department
on employee.department_id = department.id;

上述查询以 employee 为左表,department 为右表,department 中无法与 employee 匹配的 id3 的一行也会显示到最终的查询结果中,左表部分会以 NULL 显示

+------+------+---------------+--------+----+-----------+
| id   | name | department_id | salary | id | name      |
+------+------+---------------+--------+----+-----------+
|    1 | John |             1 |  50000 |  1 | Sales     |
|    2 | Jane |             1 |  55000 |  1 | Sales     |
|    3 | Bob  |             2 |  60000 |  2 | Marketing |
| NULL | NULL |          NULL |   NULL |  3 | Finance   |
+------+------+---------------+--------+----+-----------+
4 rows in set (0.00 sec)

全外连接

在 MySQL 中,没有专门的语法来实现全连接(full outer join)。但是可以通过使用左外连接和右外连接的组合来模拟实现全连接。

使用 UNION 操作符将左外连接和右外连接的结果合并在一起,从而实现全连接的效果。

select *
from employee
left join department
on employee.department_id = department.id
union
select *
from employee
right join department
on employee.department_id = department.id;

查询结果:

+------+-------+---------------+--------+------+-----------+
| id   | name  | department_id | salary | id   | name      |
+------+-------+---------------+--------+------+-----------+
|    1 | John  |             1 |  50000 |    1 | Sales     |
|    2 | Jane  |             1 |  55000 |    1 | Sales     |
|    3 | Bob   |             2 |  60000 |    2 | Marketing |
|    4 | Alice |             4 |  70000 | NULL | NULL      |
|    5 | Mark  |          NULL |  80000 | NULL | NULL      |
|    6 | Emily |          NULL |  90000 | NULL | NULL      |
| NULL | NULL  |          NULL |   NULL |    3 | Finance   |
+------+-------+---------------+--------+------+-----------+
7 rows in set (0.00 sec)
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

世真

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值