【从小白到精通之数据库篇】Mysql--连接与子查询
一、自连接(Self Join)
定义:一张表自己跟自己做 JOIN
,常用于表中存在层级关系(如员工表的“员工-上级”关系)。
1. 显式自连接
使用 JOIN
关键字明确写出连接条件。
SELECT e.emp_id, e.name AS employee, m.name AS manager
FROM employees e JOIN employees m ON e.manager_id = m.emp_id;
解释:
employees e
:员工表的一个别名employees m
:同一张表的另一个别名,代表“经理”e.manager_id = m.emp_id
:连接条件
结果:员工和对应的经理名字。
2. 隐式自连接
使用旧式的 逗号连接,再在 WHERE
子句中写条件。
SELECT e.emp_id, e.name AS employee, m.name AS manager
FROM employees e, employees m
WHERE e.manager_id = m.emp_id;
二、外连接(Outer Join)
定义:外连接会在结果中保留一张表的所有记录,即使另一张表中没有匹配。
1. 左外连接(LEFT JOIN)
保留左表所有行,右表没有匹配时用 NULL
填充。
SELECT e.name AS employee, d.dept_name
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.dept_id;
解释:
即使某员工没有部门,也会显示出来,
dept_name
为NULL
。
2. 右外连接(RIGHT JOIN)
保留右表所有行,左表没有匹配时用 NULL
填充。
SELECT e.name AS employee, d.dept_name
FROM employees e
RIGHT JOIN departments d ON e.dept_id = d.dept_id;
解释:
即使某部门没有员工,也会显示出来,
employee
为NULL
。、
在开发中更常用左外连接,因为左外连接与右外连接形式其实是等价的。只不过是被动与主动的关系。
✅ 小结
自连接:一张表连接自己,用于处理层级关系
外连接:用于保留一张表的所有记录,左外连接和右外连接形式等价
推荐做法:尽量使用显式
JOIN
,清晰易读
三、子查询(嵌套select语句)
1️⃣ 单行子查询(Single-Row Subquery)
子查询返回 一行一列
常用于
=
、>
、<
等条件比较
示例:
SELECT name, salary FROM employees WHERE salary > ( SELECT AVG(salary) FROM employees );
解释:
内层查询:
SELECT AVG(salary) FROM employees
返回全体员工的平均工资外层查询:返回工资高于平均工资的员工
结果:只显示工资高于平均值的员工
2️⃣ 多行子查询(Multi-Row Subquery)
子查询返回 多行一列
使用
IN
、NOT IN
、ANY
、ALL
等运算符
示例:
SELECT name FROM employees WHERE dept_id IN ( SELECT dept_id FROM departments WHERE location = 'Beijing' );
解释:
内层查询:找出位于北京的部门
dept_id
外层查询:查询这些部门的所有员工
结果:返回在北京部门工作的员工
3️⃣ 多列子查询(Multi-Column Subquery)
子查询返回 多列多行
使用
(col1, col2) IN (...)
或用于JOIN
替代
示例:
SELECT name, dept_id FROM employees WHERE (dept_id, job_id) IN ( SELECT dept_id, job_id FROM job_assignments WHERE status = 'active' );
解释:
内层查询:找出当前有效职位和部门组合
外层查询:查询符合这些组合的员工
4️⃣ 相关子查询(Correlated Subquery)
子查询依赖外层查询的列
每行外层数据都会执行一次子查询
示例:
SELECT e1.name, e1.salary FROM employees e1 WHERE e1.salary > ( SELECT AVG(e2.salary) FROM employees e2 WHERE e2.dept_id = e1.dept_id );
解释:
外层查询:每个员工 e1
内层查询:计算该员工所在部门的平均工资
外层只保留工资高于本部门平均工资的员工
5️⃣ 子查询在 FROM
子句中
子查询可以当作 临时表 使用
常用于复杂统计或分组
示例:
SELECT dept_id, MAX(avg_salary) AS max_avg_salary FROM ( SELECT dept_id, AVG(salary) AS avg_salary FROM employees GROUP BY dept_id ) AS dept_avg GROUP BY dept_id;
解释:
内层子查询:计算每个部门的平均工资
外层查询:从临时表中获取最大平均工资或其他统计