SQL自连接查询:轻松找出重复数据中的最大ID记录
你是否曾在编写SQL查询时,遇到过需要从同一张表中查找重复记录,并只保留其中某一条的情况?本文将通过一个典型示例,详细解析如何使用自连接(Self-Join) 高效解决这类问题。
🧠 理解自连接查询
📌 示例场景与SQL语句
假设我们有一张 Person 表,结构如下:
| Id | |
|---|---|
| 1 | a@example.com |
| 2 | b@example.com |
| 3 | a@example.com |
| 4 | c@example.com |
我们希望找出所有重复的邮箱,并只保留 Id 最大 的那一条记录。
使用的SQL语句如下:
SELECT p1.*
FROM Person p1, Person p2
WHERE p1.Email = p2.Email
AND p1.Id > p2.Id;
🔍 分步解析执行过程
第一步:自连接生成所有组合
将 Person 表视为两个别名表 p1 和 p2,进行笛卡尔积连接,生成所有可能的行组合(共 n × n 行)。
| p1 | p2 |
|---|---|
| (1, a@…) | (1, a@…) |
| (1, a@…) | (2, b@…) |
| (1, a@…) | (3, a@…) |
| … | … |
第二步:应用筛选条件
条件一:p1.Email = p2.Email
只保留邮箱相同的行组合。
条件二:p1.Id > p2.Id
进一步筛选出 p1 的 Id 大于 p2 的 Id 的组合,目的是:
- 排除自己与自己比较(Id 相等)
- 只保留“后出现”的记录(Id 更大)
第三步:最终结果
符合条件的记录即为重复邮箱中 Id 最大的那条。
✅ 结果示例
执行上述查询后,将返回:
| Id | |
|---|---|
| 3 | a@example.com |
因为:
a@example.com是重复邮箱- Id = 3 是重复中最大的 Id
📖 总结表格:关键知识点
| 概念 | 说明 | 示例 |
|---|---|---|
| 自连接 | 将同一张表视为两个不同的表进行连接 | FROM Person p1, Person p2 |
| 重复筛选 | 通过字段相等条件找出重复项 | p1.Email = p2.Email |
| 排除自身比较 | 使用 Id 大小比较避免同一行比较,并保留“后出现”的记录 | p1.Id > p2.Id |
| 适用场景 | 去重、保留最新/最大ID记录、查找重复数据等 | 用户表、订单表、日志表等均有应用场景 |
💡 常见疑问解答
❓ 为什么用 > 而不用 >=?
- 使用
>可以排除自己与自己比较(Id 相等的情况) - 使用
>=会包含自身,导致结果中出现不必要的重复
❓ 是否可以用其他方式实现?
是的,还可以使用 GROUP BY + HAVING 或 ROW_NUMBER() 窗口函数实现类似功能,但自连接在理解上更直观,且在某些数据库中有较好的性能。
🎯 一句话总结
通过自连接和条件
p1.Email = p2.Email AND p1.Id > p2.Id,可以高效找出重复数据中 Id 最大的记录,适用于多种去重场景。
如果你也遇到过类似的数据去重问题,不妨尝试使用自连接查询,简洁又高效!欢迎在评论区分享你的使用经验或疑问。
863

被折叠的 条评论
为什么被折叠?



