【MySQL基础】MySQL内连接(INNER JOIN)详解:高效关联查询的基础
在关系型数据库中,连接操作是最重要也最常用的功能之一。本文将详细介绍MySQL中最基础的连接类型——内连接(INNER JOIN),通过具体示例帮助您掌握其使用方法。
1 什么是内连接?
内连接(INNER JOIN)是MySQL中最常用的连接类型之一,它仅返回两个表中满足连接条件的匹配记录。当您需要从多个相关联的表中获取数据时,内连接提供了一种高效的方式。核心特点:
- 只返回两个表中都存在的匹配记录
- 不匹配的记录不会出现在结果集中
- 是等值连接的一种实现方式
2 基本语法与简单示例
select 列名1, 列名2, ...
from 表1
inner join 表2 on 表1.列名 = 表2.列名;
其中inner join是连接关键字,on后面指定连接条件。在实际使用中,inner关键字可以省略,直接写join默认为内连接。
- 示例1:员工与部门关联查询
-- 创建部门表与员工表
create table departments (
dept_id int primary key,
dept_name varchar(50) not null
) default charset=utf8mb4;
commit;
create table employees (
emp_id int primary key,
emp_name varchar(50) not null,
dept_id int,
salary decimal(10,2)
) default charset=utf8mb4;
commit;
-- 插入测试数据
insert into departments values (10, '研发部'), (20, '市场部'), (30, '财务部');
insert into employees values
(101, '张三', 10, 12000),
(102, '李四', 20, 9000),
(103, '王五', 10, 15000),
(104, '赵六', null, 8000);
commit;
-- 基础内连接查询
select e.emp_name, d.dept_name, e.salary
from employees e
inner join departments d on e.dept_id = d.dept_id;
- 查询结果
mysql> select e.emp_name, d.dept_name, e.salary
-> from employees e
-> inner join departments d on e.dept_id = d.dept_id;
+----------+-----------+----------+
| emp_name | dept_name | salary |
+----------+-----------+----------+
| 张三 | 研发部 | 12000.00 |
| 李四 | 市场部 | 9000.00 |
| 王五 | 研发部 | 15000.00 |
+----------+-----------+----------+
3 rows in set (0.04 sec)
mysql>
# 赵六没有出现在结果中,因为他的dept_id为null,无法匹配任何部门
3 实际应用场景演示
3.1 场景1:多条件连接查询
-- 查询研发部工资超过10000的员工
select e.emp_name, e.salary
from employees e
inner join departments d on e.dept_id = d.dept_id
where d.dept_name = '研发部' and e.salary > 10000;
mysql> select e.emp_name, e.salary
-> from employees e
-> inner join departments d on e.dept_id = d.dept_id
-> where d.dept_name = '研发部' and e.salary > 10000;
+----------+----------+
| emp_name | salary |
+----------+----------+
| 张三 | 12000.00 |
| 王五 | 15000.00 |
+----------+----------+
2 rows in set (0.03 sec)
mysql>
3.2 场景2:三表关联查询
-- 添加项目表
create table projects (
project_id int primary key,
project_name varchar(100),
leader_id int
)default charset=utf8mb4;
commit;
insert into projects values
(1, '电商系统升级', 101),
(2, '市场推广活动', 102);
commit;
-- 查询项目信息及负责人部门
select p.project_name, e.emp_name, d.dept_name
from projects p
inner join employees e on p.leader_id = e.emp_id
inner join departments d on e.dept_id = d.dept_id;
- 查询结果
mysql> select p.project_name, e.emp_name, d.dept_name
-> from projects p
-> inner join employees e on p.leader_id = e.emp_id
-> inner join departments d on e.dept_id = d.dept_id;
+--------------------+----------+-----------+
| project_name | emp_name | dept_name |
+--------------------+----------+-----------+
| 电商系统升级 | 张三 | 研发部 |
| 市场推广活动 | 李四 | 市场部 |
+--------------------+----------+-----------+
2 rows in set (0.01 sec)
mysql>
4 使用技巧
4.1 索引优化
-- 为关联字段创建索引
alter table employees add index idx_dept (dept_id);
alter table projects add index idx_leader (leader_id);
4.2 避免常见错误
-- 错误写法:忘记写on条件(产生笛卡尔积)
select * from employees, departments;
-- 正确写法
select * from employees inner join departments on employees.dept_id = departments.dept_id;
4.3 表别名规范
-- 不推荐写法
select employees.emp_name, departments.dept_name from employees inner join departments on employees.dept_id = departments.dept_id;
-- 推荐写法
select e.emp_name, d.dept_name from employees e inner join departments d on e.dept_id = d.dept_id;
4.4 条件位置区分
-- on子句指定连接条件
-- where子句进行结果过滤
select e.emp_name, d.dept_name
from employees e
inner join departments d on e.dept_id = d.dept_id
where e.salary > 10000;
5 内连接与其他连接对比
-- 内连接(只返回匹配记录)
select e.emp_name, d.dept_name from employees e inner join departments d on e.dept_id = d.dept_id;
-- 左连接(保留左表所有记录)
select e.emp_name, d.dept_name from employees e left join departments d on e.dept_id = d.dept_id;
-- 右连接(保留右表所有记录)
select e.emp_name, d.dept_name from employees e right join departments d on e.dept_id = d.dept_id;
- 查询结果
mysql> -- 内连接(只返回匹配记录)
mysql> select e.emp_name, d.dept_name from employees e inner join departments d on e.dept_id = d.dept_id;
+----------+-----------+
| emp_name | dept_name |
+----------+-----------+
| 张三 | 研发部 |
| 李四 | 市场部 |
| 王五 | 研发部 |
+----------+-----------+
3 rows in set (0.00 sec)
mysql>
mysql> -- 左连接(保留左表所有记录)
mysql> select e.emp_name, d.dept_name from employees e left join departments d on e.dept_id = d.dept_id;
+----------+-----------+
| emp_name | dept_name |
+----------+-----------+
| 张三 | 研发部 |
| 王五 | 研发部 |
| 李四 | 市场部 |
| 赵六 | NULL |
+----------+-----------+
4 rows in set (0.03 sec)
mysql>
mysql> -- 右连接(保留右表所有记录)
mysql> select e.emp_name, d.dept_name from employees e right join departments d on e.dept_id = d.dept_id;
+----------+-----------+
| emp_name | dept_name |
+----------+-----------+
| 张三 | 研发部 |
| 李四 | 市场部 |
| 王五 | 研发部 |
| NULL | 财务部 |
+----------+-----------+
4 rows in set (0.00 sec)
mysql>
6 内连接的使用注意事项
- 连接条件的选择:确保on子句中的连接条件正确,错误的连接条件可能导致笛卡尔积(两个表所有行的组合),极大影响性能。
- 表别名:为表指定简短的别名(如u、o)可以提高SQL的可读性。
- 性能优化:连接字段最好建立索引,特别是大表连接时。
- 多表连接:可以连接多个表,但要注意连接顺序和条件
7 总结
- 左连接(LEFT JOIN):返回左表所有记录,即使右表没有匹配
- 右连接(RIGHT JOIN):返回右表所有记录,即使左表没有匹配
- 全连接(FULL JOIN):返回左右两表所有记录(MySQL不直接支持)
内连接是日常开发中最常用的连接方式,掌握它对于高效数据库查询至关重要。通过合理使用内连接,您可以轻松地从多个相关表中提取所需数据,构建复杂的业务查询。