比较同一表中的行
掌握使用自连接查找配对项、重复项和相邻记录的模式
比较同一表中的行 是 CoddyKit 上的免费 SQL Interview Prep 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Interview Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Interview Prep 课程共包含 4 节课。
使用自连接进行行间比较
除了层次结构之外,自连接的另一个主要用途是相互比较同一张表中的行。您可以将任意行配对,以查找重复项、近似匹配项或相邻记录,而不只是处理父子关系。
模式不变:为表指定两个别名,并编写一个能够表达两行之间关系的 ON 条件。
查找同组中的配对行
一个经典问题是:找出所有在同一部门工作的员工配对。根据部门相等这一条件将表与自身连接,同时确保两行彼此不同。
简单的连接还会将每名员工与自己配对,并使每个配对出现两次。下一步我们会解决这个问题。
SELECT a.name, b.name, a.department
FROM employees a
JOIN employees b ON a.department = b.department;移除自身配对和镜像重复项
在同组配对中有两个问题:一行会与自身匹配(Alice 与 Alice),并且每个配对会出现两次(Alice-Bob 和 Bob-Alice)。
使用一个不等式即可同时解决这两个问题:a.id < b.id。它能保证两行不同,并且每个配对只保留一种排列顺序。
SELECT a.name, b.name, a.department
FROM employees a
JOIN employees b
ON a.department = b.department
AND a.id < b.id;为什么使用 a.id < b.id,而不是 a.id <> b.id
使用 a.id <> b.id 可以移除自身配对,但仍会返回两种排列顺序,使结果数量翻倍。使用 a.id < b.id 则能同时移除自身配对,并一次性去除镜像重复项。
面试官会特别关注您选择 < 还是 <>;这能体现您是否理解自连接背后的组合数学。
-- <> keeps Alice-Bob AND Bob-Alice (duplicated)
-- < keeps only Alice-Bob (correct unique pairs)查找重复行
若要查找在关键列上彼此重复的记录,请根据这些列执行自连接,并要求主键不同。
这里我们找出共享同一电子邮件地址的客户。a.id < b.id 可以让每个重复配对只出现一次。通常,使用 GROUP BY ... HAVING COUNT(*) > 1 会更简洁,但自连接可以将实际重复的记录对并排展示出来。
SELECT a.id, b.id, a.email
FROM customers a
JOIN customers b
ON a.email = b.email
AND a.id < b.id;比较相邻记录
分析工作中经常需要将每一行与序列中的下一行进行比较,例如比较每天的销售额与前一天的销售额。自连接可以将连续的行配对。
这里我们将每天与恰好早一天的那一行连接,以计算变化量。当序列没有间隔时,这种方法有效。
SELECT t.day, t.amount,
t.amount - y.amount AS change_vs_prev
FROM daily_sales t
JOIN daily_sales y
ON y.day = t.day - INTERVAL '1 day';相邻自连接中的间隔问题
如果缺少某一天,上一个查询就会失效:因为不存在恰好早一天的记录,所以该行会被排除(INNER JOIN),或者您必须处理 NULL 值。
这就是为什么面试官经常会引导您使用 窗口函数,例如使用 LAG 来“与上一行比较”。窗口函数依据序号位置而不是值匹配,因此能够自然地应对间隔。
-- LAG handles gaps; the self join assumed contiguous days
SELECT day, amount,
amount - LAG(amount) OVER (ORDER BY day) AS change_vs_prev
FROM daily_sales;自连接与窗口函数
请了解其中的权衡:
- 自连接通过值之间的关系(相同部门、之前的日期)比较行。它很灵活,但可能造成行数扩增,也可能无法正确处理间隔。
- 窗口函数根据有序分区内的序号位置进行比较。对于上一行/下一行逻辑,它更简洁。
对于“与相邻行比较”,请优先使用 LAG/LEAD。对于“查找所有符合条件的成对行”,自连接是自然的工具。
找出优于同组成员的行
另一种模式是:找出薪资高于所在部门至少一名同事的员工。自连接可以直接表达这一点。
我们将每名员工与同部门中薪资更低的其他员工连接,然后保留出现过的去重员工。读起来几乎就像那句中文描述。
SELECT DISTINCT a.name, a.department, a.salary
FROM employees a
JOIN employees b
ON a.department = b.department
AND a.salary > b.salary;注意行数扩增
在非唯一列上进行自连接会使行数成倍增加。在一个有 100 人的部门内配对时,过滤前大约会产生 100 x 100 个候选对。
始终加入去重谓词(a.id < b.id),并在只需要参与连接的行而非每个成对结果时,添加 DISTINCT 或使用分组。面试时请提到您对这种行数扩增的认识。
选择比较工具
表内比较的决策指南:
- 所有匹配的成对结果(重复项、同组组合):使用自连接和
a.id < b.id。 - 有序序列中的上一行/下一行:窗口函数(
LAG/LEAD)。 - 将每行与分组聚合结果比较:相关子查询或窗口聚合。
快速检查
您希望得到所有共享相同类别的产品的唯一配对结果,不允许产品与自身配对,也不允许出现重复的排列顺序。
回顾:比较同一表中的行
要点:
- 将表与自身进行自连接,可以为查找重复项和生成同组组合配对其自身的行。
- 使用
a.id < b.id,通过一个谓词同时排除自身配对和镜像重复项。 - 基于自连接的相邻行比较会因间隔而失效;对于上一行/下一行逻辑,请优先使用
LAG/LEAD。 - 在非唯一列上连接时,始终考虑行数扩增。
常见问题解答
「比较同一表中的行」课时是免费的吗?
是的 — 「比较同一表中的行」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Interview Prep 课程的其余内容,请升级到 CoddyKit PRO。 SQL Interview Prep 课程共包含 4 节课。
「比较同一表中的行」这节课中我会学到什么?
掌握使用自连接查找配对项、重复项和相邻记录的模式 你通过在浏览器中直接运行的动手代码来练习 SQL Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 SQL Interview Prep 需要有经验吗?
无需任何先前经验。CoddyKit 上的 SQL Interview Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「比较同一表中的行」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 SQL Interview Prep 课中编写并运行代码吗?
能。每节 SQL Interview Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。