在 SQL 中,自连接(Self Join) 是指一张表与自身进行连接,常用于处理层级结构(如员工与经理)、前后记录对比等场景。自连接时重复行的处理主要取决于连接方式(INNER / LEFT)、连接条件以及数据本身的重复情况。
下面系统说明自连接如何处理重复行。
假设有表 emp:
| id | name | manager_id |
|---|---|---|
| 1 | A | NULL |
| 2 | B | 1 |
| 3 | C | 1 |
| 4 | D | 2 |
自连接示例:
SELECT e1.name AS emp, e2.name AS mgr
FROM emp e1
JOIN emp e2
ON e1.manager_id = e2.id;
如果 manager_id 或 id 存在重复值,就可能产生重复行。
如果 emp.id 有重复(不应发生,但数据脏时可能):
e1.manager_id = e2.id
e1 行会匹配多个 e2 行✅ 解决方式:
DISTINCTSELECT DISTINCT e1.name, e2.name
FROM emp e1
JOIN emp e2 ON e1.manager_id = e2.id;
示例:比较相邻工资
SELECT a.id, b.id
FROM salary a
JOIN salary b
ON a.id = b.id - 1;
如果 id 不连续或有重复:
✅ 建议:
LAG(salary) OVER (ORDER BY id)
SELECT e1.name, e2.name
FROM emp e1
LEFT JOIN emp e2
ON e1.manager_id = e2.id;
e2 为 NULL✅ 若只想看有经理的:
INNER JOIN
如果表中有完全重复行(无主键):
SELECT a.*, b.*
FROM t a
JOIN t b ON a.col = b.col;
会产生 N × N 行。
✅ 解决:
WITH t_uniq AS (
SELECT DISTINCT * FROM t
)
SELECT ...
✅ 1. 使用主键或唯一键连接
ON a.id = b.parent_id
✅ 2. 必要时使用 DISTINCT
SELECT DISTINCT ...
✅ 3. 使用窗口函数替代自连接
ROW_NUMBER() OVER (PARTITION BY ...)
LAG() / LEAD()
✅ 4. 明确连接类型
自连接本身不会“自动去重”,重复行由连接键是否唯一、数据是否重复、连接条件决定;应通过唯一键、DISTINCT 或窗口函数来控制。
如果你有具体 SQL 或业务场景(如树形结构、前后对比),我可以帮你改写并优化。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。