SELF JOIN 就是把一张表和它自己连接起来。刚开始看可能有点奇怪:为啥要让表和自己连?但实际开发中这种需求还挺常见的。比如,你有个员工表,每个员工都有个manager。manager其实也是员工,所以数据也在同一张表里。SELF JOIN 就能帮我们把员工和他们的manager对上。
正式点说,SELF JOIN 就是普通的 JOIN,不过我们把同一张表用两次,给它们起不同的别名(alias),这样就能区分“两个版本”的表了。
SELF JOIN 可以用来:
- 层级关系:比如“父-子”关系,像员工和他的manager。
- 分析表内数据:比如比对表里的记录,找相似的商品或事件。
- 处理有重复逻辑的复杂查询。
SELF JOIN 的语法
为了更直观,直接看下 SELF JOIN 的简化语法:
SELECT
A.column_name,
B.column_name
FROM
table_name A
JOIN
table_name B
ON
A.common_column = B.common_column;
这里:
table_name A和table_name B是同一张表,只是别名不一样。A.common_column和B.common_column是用来连接记录的字段。
别名(A 和 B)就是让数据库知道你现在操作的是“哪一份”表。
SELF JOIN 的用法举例
例1:员工和他们的manager列表
假设我们有一张 employees 表,长这样:
| employee_id | name | manager_id |
|---|---|---|
| 1 | Alex Lin | NULL |
| 2 | Maria Chi | 1 |
| 3 | Otto Song | 1 |
| 4 | Nina Zhao | 2 |
这张表里:
employee_id—— 员工ID。name—— 员工名字。manager_id—— manager的ID,其实就是另一个员工的employee_id。
目标:查出员工和他们的manager。
用 SELF JOIN 这样写:
SELECT
e.name AS employee_name,
m.name AS manager_name
FROM
employees e
LEFT JOIN
employees m
ON
e.manager_id = m.employee_id;
结果:
| employee_name | manager_name |
|---|---|
| Alex Lin | NULL |
| Maria Chi | Alex Lin |
| Otto Song | Alex Lin |
| Nina Zhao | Maria Chi |
这里:
- 表
e—— “员工”。 - 表
m—— 其实也是“员工”,不过这次是当“manager”用。
Alex Lin 没有manager(manager_id = NULL),所以 manager_name 那一列是空的。
例2:查找相似商品
假设有张 products 表:
| product_id | product_name | category |
|---|---|---|
| 1 | 冰箱 | 电器 |
| 2 | 洗衣机 | 电器 |
| 3 | 智能手机 | 数码 |
| 4 | 平板 | 数码 |
目标:找出属于同一类别的商品对。
用 SELF JOIN 这样写:
SELECT
p1.product_name AS product_1,
p2.product_name AS product_2
FROM
products p1
JOIN
products p2
ON
p1.category = p2.category
AND
p1.product_id < p2.product_id;
结果:
| product_1 | product_2 |
|---|---|
| 冰箱 | 洗衣机 |
| 智能手机 | 平板 |
注意 p1.product_id < p2.product_id 这个条件。这样可以避免结果里出现重复的组合,比如 冰箱 — 洗衣机 和 洗衣机 — 冰箱。
例3:分析层级结构(父类和子类)
再看一个例子。假设有张 categories 表:
| category_id | category_name | parent_id |
|---|---|---|
| 1 | 电器 | NULL |
| 2 | 数码 | 1 |
| 3 | 电脑 | 1 |
| 4 | 智能手机 | 2 |
这里:
category_id—— 分类ID。category_name—— 分类名。parent_id—— 父分类的ID。
目标:把分类和它的父分类对上。
查询:
SELECT
c1.category_name AS child_category,
c2.category_name AS parent_category
FROM
categories c1
LEFT JOIN
categories c2
ON
c1.parent_id = c2.category_id;
结果:
| child_category | parent_category |
|---|---|
| 电器 | NULL |
| 数码 | 电器 |
| 电脑 | 电器 |
| 智能手机 | 数码 |
用 SELF JOIN 时常见的坑
忘了写别名: 如果不写别名,根本分不清哪份表是哪份。
循环引用: 如果数据里有循环引用(比如员工自己是自己的manager),结果可能会很奇怪。
结果重复: 记得要过滤下结果(比如用 p1.product_id < p2.product_id),不然会有重复。
SELF JOIN 是处理数据时很强大的工具,用好了能搞定层级结构、表内关系、数据分析这些复杂需求。希望你现在能体会到,这个SQL里的“自拍”有多实用!
GO TO FULL VERSION