多表联合查询
1. 分类
查询两个及以上的表,主要分类如下:
| 多表查询类型 | 说明与关键字 | 语法示例 |
|---|---|---|
| 交叉连接 | 产生笛卡尔积,一般仅用于了解,不推荐业务使用 | select * from A, B; |
| 内连接 | 只返回两表中匹配到的行,inner 可省略;分为隐式(SQL92)和显式(SQL99)写法 |
隐式:select * from A, B where A.id = B.a_id;显式:select * from A inner join B on A.id = B.a_id; |
| 左外连接 | 左表全部返回,右表只返回匹配行,不匹配显示 NULL;outer 可省略 |
select * from A left outer join B on A.id = B.a_id; |
| 右外连接 | 右表全部返回,左表只返回匹配行,不匹配显示 NULL;outer 可省略 |
select * from A right outer join B on A.id = B.a_id; |
| 满外连接 | 两表全部返回,不匹配的一侧显示 NULL;MySQL 不原生支持,可用 union 模拟 | select * from A full outer join B on A.id = B.a_id; |
| 子查询 | select 嵌套,在查询中再嵌套查询,用于条件或结果集 |
select * from A where id in (select a_id from B); |
| 表自关联 | 将同一张表当成多张表使用,通过别名区分,常用于层级 / 递归场景 | select a.name, b.name from emp a join emp b on a.mgr = b.empno; |
参考图示:

数据准备:
sql
create database if not exists mydb3;
use mydb3;
-- 创建部门表
create table if not exists dept3 (
deptno varchar(20) primary key, -- 部门号
name varchar(20) -- 部门名字
);
-- 创建员工表
create table if not exists emp3 (
eid varchar(20) primary key, -- 员工编号
ename varchar(20), -- 员工名字
age int, -- 员工年龄
dept_id varchar(20) -- 员工所属部门
);
-- 给dept3表添加数据
insert into dept3 values('1001','研发部');
insert into dept3 values('1002','销售部');
insert into dept3 values('1003','财务部');
insert into dept3 values('1004','人事部');
-- 给emp3表添加数据
insert into emp3 values('1','乔峰',20, '1001');
insert into emp3 values('2','段誉',21, '1001');
insert into emp3 values('3','虚竹',23, '1001');
insert into emp3 values('4','阿紫',18, '1001');
insert into emp3 values('5','扫地僧',85, '1002');
insert into emp3 values('6','李秋水',33, '1002');
insert into emp3 values('7','鸠摩智',50, '1002');
insert into emp3 values('8','天山童姥',60, '1003');
insert into emp3 values('9','慕容博',58, '1003');
insert into emp3 values('10','丁春秋',71, '1005');
2. 交叉连接查询
返回被连接的两个表的所有数据行的笛卡尔积(理解为一张表的每一行去和另一张表的任意一行进行匹配),例如A表有m行数据,B表有n行数据,则返回 m*n 行数据。笛卡尔积会产生很多冗余数据,需要进行条件筛选。
语法格式:
sql
select * from 表1,表2,表3,...;
举例:
sql
select * from emp3,dept3;
3. 内连接查询
查询多张表的交集。
语法格式:
sql
-- 隐式内连接
select * from A,B where 条件;
-- 显式内连接
select * from A inner join B on 条件;
举例:
sql
-- 查询每个部门的所属员工
select * from dept3,emp3 where dept3.deptno = emp3.dept_id;
-- 或
select * from dept3 inner join emp3 on dept3.deptno = emp3.dept_id;
-- 查询研发部门的所属员工
select
dept3.name,emp3.ename
from
dept3
inner join
emp3
on
dept3.deptno = emp3.dept_id
where
dept3.name = '研发部';
-- 查询研发部和销售部的所属员工
select
dept3.name,emp3.ename
from
dept3
inner join
emp3
on
dept3.deptno = emp3.dept_id
where
dept3.name = '研发部' || dept3.name = '销售部';
-- 查询每个部门的员工数,并升序排序
select
dept3.name,count(emp3.ename)
from
dept3
inner join
emp3
on
dept3.deptno = emp3.dept_id
group by
dept3.name
order by
count(ename) asc;
-- 查询人数大于等于3的部门,并按照人数降序排序
select
dept3.name,count(emp3.ename) as total_number
from
dept3
inner join
emp3
on
dept3.deptno = emp3.dept_id
group by
dept3.name
having
total_number > 3
order by
total_number desc;
4. 外连接查询
外连接分为左外连接(left outer join)、右外连接(right outer join)、满外连接(full outer join)。
语法格式:
sql
-- 左外连接
select * from 表1 left outer join 表2 on 条件;
-- 右外连接
select * from 表1 right outer join 表2 on 条件;
-- 满外连接
select * from 表1 full outer join 表2 on 条件;
举例: