419 字
2 分钟
MySQL学习笔记 (7)
2026-08-31
NOTE

基于 MySQL 26.7。JOIN

JOIN#

JOIN 用于把两个或多个表的行结合起来。

最常见的是 INNER JOIN:只返回两个表中匹配的行。

SELECT e.last_name, d.dept_name
FROM employee AS e
INNER JOIN department AS d
ON e.dept_no = d.dept_no;

连接条件写在 ON 后面。两表列名相同时,也可以用 USING (dept_no)

列名冲突时要写成 表名.列名别名.列名

LEFT JOIN / RIGHT JOIN#

LEFT JOIN 返回左表的全部行。右表没有匹配时,右表的列是 NULL。

SELECT e.last_name, d.dept_name
FROM employee AS e
LEFT JOIN department AS d
ON e.dept_no = d.dept_no;

RIGHT JOIN 返回右表的全部行。左表没有匹配时,左表的列是 NULL。

OUTER 可以省略:LEFT OUTER JOINLEFT JOIN 相同。

CROSS JOIN#

CROSS JOIN 返回两个表的笛卡尔积,也就是每行与另一表的每一行组合。

SELECT *
FROM employee
CROSS JOIN department;

CROSS JOIN 不写 ON

UNION#

UNION 用于合并两个 SELECT 的结果。

SELECT dept_no FROM employee
UNION
SELECT dept_no FROM department;
  • UNION:去掉重复行
  • UNION ALL:保留重复行

两边选出的列数要相同。

ORDER BY 写在整个 UNION 的最后。

还可以用 INTERSECT(交集)和 EXCEPT(差集):

SELECT dept_no FROM employee
INTERSECT
SELECT dept_no FROM department;
SELECT dept_no FROM employee
EXCEPT
SELECT dept_no FROM department;

子查询#

子查询是嵌套在另一条语句里的查询。

下面找出工资高于平均工资的员工:

SELECT last_name
FROM employee
WHERE salary > (SELECT AVG(salary) FROM employee);

EXISTS 判断子查询是否返回了行:

SELECT last_name
FROM employee AS e
WHERE EXISTS (
SELECT *
FROM department AS d
WHERE d.dept_no = e.dept_no
AND d.director = '院长'
);

FROM 后面的子查询必须起别名:

SELECT dept_no, n
FROM (
SELECT dept_no, COUNT(*) AS n
FROM employee
GROUP BY dept_no
) AS t
WHERE n >= 2;

参考#

  1. MySQL 26.7 · JOIN
  2. MySQL 26.7 · Set Operations
  3. MySQL 26.7 · Subqueries
  4. MySQL 26.7 · EXISTS
  5. ISO/IEC 9075(SQL<2023>
MySQL学习笔记 (7)
https://blog.chuwu.top/posts/sql/mysql7/
作者
ChuwuYo
发布于
2026-08-31
许可协议
CC BY-NC-SA 4.0