0Pricing
SQL Interview Prep · 课时

比较同一表中的行

掌握使用自连接查找配对项、重复项和相邻记录的模式

比较同一表中的行 是 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 反馈 — 无需本地设置。

此课程中的所有课时

  1. CROSS JOIN 与笛卡尔积
  2. 使用 SELF JOIN 处理层级关系
  3. 比较同一表中的行
  4. 选择正确的连接类型
← 返回 SQL Interview Prep