【MySQL 学习笔记 _ Day12】分组统计进阶 + 多表连接实战(企业高频场景)
【MySQL 学习笔记 | Day12】分组统计进阶 + 多表连接实战(企业高频场景)
大家好,我是白鹿为溪~ 本期是MySQL基础系列第十二天内容,承接第十一天的SQL高级查询实战、索引优化落地,今天我们聚焦「多表连接实战」与「分组统计进阶」,彻底打通 MySQL 企业级查询的核心能力,全程干货无冗余,新手能夯实基础,进阶者能适配企业实战场景。
一、前言
Day11 我们掌握了 GROUP BY 基础分组、聚合函数与 HAVING 过滤,今天我们在这个基础上,深入学习多表连接(JOIN)的实战用法、WHERE 与 HAVING 的执行顺序差异,以及企业报表开发中最常用的分组统计+多表关联场景,帮大家跳出单表查询的局限,适配企业真实开发需求。
二、核心知识点回顾与拓展(承接 Day11,不重复)
1. 先分清:WHERE 与 HAVING 的本质区别(企业面试高频)
很多新手会混淆这两个条件过滤关键字,这里用一句话讲透:WHERE 过滤行,HAVING 过滤组,具体差异如下表所示:
| 关键字 | 执行时机 | 过滤对象 | 能否使用聚合函数 | 典型场景 |
|---|---|---|---|---|
WHERE |
GROUP BY 之前 |
原始数据行 | ❌ 不能 | 过滤未分组的原始数据(如薪资>5000的员工) |
HAVING |
GROUP BY 之后 |
分组后的聚合结果 | ✅ 可以 | 过滤分组统计结果(如部门平均薪资>6000的部门) |
💡 划重点:WHERE 是在分组前过滤“行”,筛选出符合条件的原始数据再分组;HAVING 是在分组后过滤“组”,筛选出符合条件的聚合结果,这是两者最核心的区别。
2. 多表连接(JOIN)入门:企业级关联查询的基础
Day11 我们用单表做分组统计,而企业开发中,90%的查询都需要关联多张表(比如员工表和部门表、订单表和用户表),把分散在不同表的数据合并查询,这就是多表连接的核心作用。
#### 核心概念
多表连接就是通过两张表的关联字段(如员工表和部门表的 dept\_id),建立表与表之间的关联关系,从而合并查询所需数据。
#### 最常用的 3 种连接类型(必掌握)
1. INNER JOIN(内连接):只返回两张表中都匹配的数据,是企业开发中最常用的连接方式(比如查询有员工的部门信息)。
2. LEFT JOIN(左连接):以左表为基准,返回左表所有数据,右表匹配不到的字段显示 NULL(比如查询所有部门,包括没有员工的部门)。
3. RIGHT JOIN(右连接):和左连接相反,以右表为基准,返回右表所有数据,左表匹配不到的字段显示 NULL(使用频率低于左连接)。
三、实战场景:分组统计 + 多表连接(企业报表开发高频)
#### 场景需求
按部门统计员工薪资,同时显示部门名称,只保留平均薪资>6000的部门,显示字段:部门ID、部门名称、员工人数、平均薪资、最高薪资、最低薪资,按部门ID升序排列。
#### 实战 SQL(可直接复制执行)
SELECT
d.dept_id,
d.dept_name, -- 关联部门表,获取部门名称
COUNT(e.emp_id) AS emp_count,
ROUND(AVG(e.salary), 2) AS avg_salary,
MAX(e.salary) AS max_salary,
MIN(e.salary) AS min_salary
FROM emp e
INNER JOIN dept d ON e.dept_id = d.dept_id -- 关联员工表和部门表
GROUP BY d.dept_id, d.dept_name -- 非聚合字段都要加入GROUP BY
HAVING AVG(e.salary) > 6000 -- 过滤分组后的结果
ORDER BY d.dept_id;
#### 关键要点(避坑重点)
1. 多表连接必须指定关联条件(ON e\.dept\_id = d\.dept\_id),否则会产生笛卡尔积(两张表的所有数据两两组合,数据量暴增,导致查询卡死)。
2. 关联后,SELECT 中的非聚合字段(如 dept\_name)必须加入 GROUP BY,符合 SQL 标准(MySQL 5.7+ 开启严格模式后,不添加会直接报错)。
3. 聚合函数的过滤必须用 HAVING,不能用 WHERE(WHERE 无法过滤聚合结果)。
四、避坑指南:新手最容易踩的 3 个多表连接坑
1. 笛卡尔积问题:忘记写 ON 关联条件,导致两张表的所有数据两两组合,数据量暴增(比如 emp 表10条数据、dept 表4条数据,会产生40条无效数据),查询效率极低。
2. 别名不统一:表别名前后不一致(如 FROM emp e 后面却写 p\.dept\_id),导致语法错误,无法执行查询。
3. GROUP BY 字段不全:关联多张表后,SELECT 中所有非聚合字段(如 dept_id、dept_name)都要加入 GROUP BY,否则会报错或返回错误结果。
五、今日学习总结
1. 彻底分清了WHERE 与 HAVING 的执行顺序与适用场景,掌握了“行过滤”和“组过滤”的核心逻辑。
2. 入门了多表连接,重点掌握了企业最常用的 INNER JOIN 用法,理解了多表关联的原理和关联条件的重要性。
3. 完成了企业高频的「分组统计+多表连接」实战场景,能独立写出带部门名称的员工薪资统计报表,适配企业报表开发需求。
六、配套 5 道企业级 MySQL 练习题(适配 Day12 难度,不重复、不太难)
基于 emp(员工表)和 dept(部门表)设计,贴合当前学习进度,重点练习多表连接与分组统计,每道题附参考答案和知识点解析,新手可直接上手练习。
第1题:基础多表连接(内连接)
#### 题目
查询所有员工的姓名、薪资、部门名称、部门地址,按员工薪资降序排列。
#### 参考答案
SELECT
e.emp_name,
e.salary,
d.dept_name,
d.dept_address
FROM emp e
INNER JOIN dept d ON e.dept_id = d.dept_id
ORDER BY e.salary DESC;
#### 知识点
INNER JOIN 内连接的基础用法,通过关联字段 dept\_id 合并两张表的数据,实现多表字段联合查询。
第2题:左连接统计(含空值处理)
#### 题目
查询所有部门的员工人数,包括没有员工的部门,显示部门ID、部门名称、员工人数,员工人数为0的显示0。
#### 参考答案
SELECT
d.dept_id,
d.dept_name,
COUNT(e.emp_id) AS emp_count
FROM dept d
LEFT JOIN emp e ON d.dept_id = e.dept_id
GROUP BY d.dept_id, d.dept_name;
#### 知识点
LEFT JOIN 左连接的用法,以部门表为基准,保留所有部门数据;COUNT\(e\.emp\_id\) 会自动忽略 NULL 值,没有员工的部门会显示0。
第3题:多表连接 + 条件过滤
#### 题目
查询部门地址为「北京」的所有员工信息,显示员工姓名、性别、薪资、部门名称,按入职日期升序排列。
#### 参考答案
SELECT
e.emp_name,
e.gender,
e.salary,
d.dept_name
FROM emp e
INNER JOIN dept d ON e.dept_id = d.dept_id
WHERE d.dept_address = '北京'
ORDER BY e.entry_date ASC;
#### 知识点
WHERE 过滤关联后的原始数据,多表连接后,可通过关联表的字段(如 d\.dept\_address)进行条件筛选。
第4题:分组统计 + 多表连接 + HAVING
#### 题目
统计每个部门的员工平均薪资,只显示平均薪资在5000-7000之间的部门,显示部门ID、部门名称、员工人数、平均薪资,按平均薪资升序排列。
#### 参考答案
SELECT
d.dept_id,
d.dept_name,
COUNT(e.emp_id) AS emp_count,
ROUND(AVG(e.salary), 2) AS avg_salary
FROM emp e
INNER JOIN dept d ON e.dept_id = d.dept_id
GROUP BY d.dept_id, d.dept_name
HAVING avg_salary BETWEEN 5000 AND 7000
ORDER BY avg_salary ASC;
#### 知识点
多表连接与分组统计结合,HAVING 过滤聚合结果,ROUND\(\) 函数保留平均薪资2位小数,贴合企业报表展示需求。
第5题:聚合函数 + 条件统计
#### 题目
统计每个部门的男女员工人数,显示部门ID、部门名称、男员工人数、女员工人数,按部门ID升序排列。
#### 参考答案
SELECT
d.dept_id,
d.dept_name,
SUM(CASE WHEN e.gender = '男' THEN 1 ELSE 0 END) AS male_count,
SUM(CASE WHEN e.gender = '女' THEN 1 ELSE 0 END) AS female_count
FROM emp e
INNER JOIN dept d ON e.dept_id = d.dept_id
GROUP BY d.dept_id, d.dept_name
ORDER BY d.dept_id;
#### 知识点
CASE WHEN 条件统计的用法,结合 SUM\(\) 聚合函数,实现按性别分组统计,是企业报表中常见的条件统计场景。
七、明日预告
Day13 我们将学习 MySQL 索引基础与优化技巧,结合今日的多表查询,讲解如何通过索引提升查询效率,解决企业开发中“查询变慢”的问题,同时配套面试高频索引题,帮大家提前备战面试。
八、踩坑记录(可选,建议添加)
今日练习多表连接时,曾忘记写ON 关联条件,导致出现笛卡尔积,查询结果异常;后来通过添加关联条件 ON e\.dept\_id = d\.dept\_id,成功解决问题。提醒大家:多表连接一定要写关联条件,避免踩坑!
---
✨ 我是白鹿为溪,专注 MySQL 基础学习与实战分享,每天进步一点点,坚持带来高质量学习笔记,欢迎关注、收藏,一起夯实 MySQL 基础,备战企业面试!
(注:文档部分内容可能由 AI 生成)

浙公网安备 33010602011771号