前沿部署工程师的工作深入客户数据之中,因此 SQL 环节分量很重,而且比简单的 SELECT/WHERE 筛选要求更高。面试题是针对真实模式的多步数据转换,考察的是你对正确性的推理能力:粒度、连接、NULL 和窗口函数。只要一个连接写错,你就会在不知不觉中把某个指标重复计算,而这正是面试官想要探测的失败点。

这是一份题库,而不是语法复习资料。它汇集了前沿部署工程师面试中反复出现的 SQL 题目,按主题分组,每题附有简短的解题思路说明。先阅读了解题型,然后在 Rung 的实时 SQL 练习场中亲手编写查询——它运行在真实的浏览器内数据库上,并会将你的结果与参考答案进行核对。

窗口函数类题目

窗口函数是 FDE SQL 面试中最大的分水岭。它能回答“按组”的问题,而不会像 GROUP BY 那样把行折叠掉。如果只能专攻一个领域,就专攻这里。

找出每位客户的首次购买

ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY purchased_at) 为每行在客户内部赋予一个排名;在外层查询或 CTE 中筛选排名为 1 的行。要说明为什么仅用 GROUP BY 无法干净地做到这一点(你会丢失首行其他列的数据)。

计算每位客户随时间变化的累计总额

SUM(amount) OVER (PARTITION BY customer_id ORDER BY event_date) 会随着窗口滑动而累加。要明确说明排序方式,如果被问到,还要说明窗口帧(默认是从无界起点到当前行),这正是容易隐藏细微错误答案的地方。

在每个区域内按收入对前 3 名产品进行排名

这是“每组前 N 名”类题目。用 RANK() 或 ROW_NUMBER() 按 region 分区、按收入降序排序进行排名,然后筛选出前 3 名。要提到 RANK(并列共享排名,后续出现间隔)与 ROW_NUMBER(任意打破平局)之间的区别,这样才能有意识地选对函数。

用 LAG 计算环比变化

LAG(revenue) OVER (PARTITION BY customer_id ORDER BY month) 会把上一期的值拉到当前行,方便你做减法。要有意识地处理第一期 LAG 为 NULL 的情况,而不是让它悄悄消失。

将客户划分到十分位或四分位

NTILE(4) OVER (ORDER BY total_spend) 会把行均匀分桶,用于群组分析。这表明你能把原始指标转化为面向客户的报告所需的细分。

连接、粒度与聚合类题目

这些题目考察你能否从多张表中得出正确的数字。经典的失败是静默的扇出——连接一对多关系导致重复计数。优秀的候选人会在连接前说明每张表的粒度,并在之后对行数做合理性检查。

按客户统计跨订单和订单明细的总收入

将客户连接到订单再连接到订单明细会使行数成倍增加,因此在连接后对订单总额求和会导致重复计算。先把订单明细聚合到订单粒度(放在一个 CTE 中),再向上连接。过程中要说明“一行代表一条订单明细”与“一行代表一个订单”的区别。

没有订单的客户(反连接)

使用带 WHERE orders.id IS NULL 过滤条件的 LEFT JOIN,或 NOT EXISTS,可以找出这些缺口。要指出当子查询返回 NULL 时 NOT IN 会静默失效,这是一个经典陷阱。

每天统计去重后的活跃用户数

使用 COUNT(DISTINCT user_id) 并按天分组。微妙之处在于如何定义“活跃”,以及如何处理一天内出现多次的用户,所以写代码前先说明你的定义。

用 HAVING 而不是 WHERE 过滤分组

“订单数超过 5 的客户”是对聚合结果进行过滤,所以应放在 GROUP BY 之后的 HAVING 中,而不是 WHERE。正确把握这个边界说明你真正理解了求值顺序。

用条件聚合将行转置为列

SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) 可以在一次扫描中将状态列转换为各状态的小计。这是不依赖特定数据库语法、可移植的行转列方法。

同期群、漏斗与正确性问题

更难的轮次会深入到客户真正会提出的分析需求,以及那些能区分细心工程师与其他人的 NULL 和正确性陷阱。

月度留存或同期群分析

将每个用户分配到其注册月份的同期群,然后统计每个后续月份中有多少用户活跃。在一个 CTE 中构建同期群,在另一个 CTE 中构建活跃数据,然后按同期群加时间偏移进行连接。一开始就说明你如何定义“活跃”和“留存”。

步骤之间的漏斗转化

统计到达步骤 1、然后步骤 2、然后步骤 3 的用户数,通常使用条件聚合或对有序事件进行连续的 LEFT JOIN。注意跳过或重复某个步骤的用户。

过滤和聚合中的 NULL 处理

NULL 不等于任何值,所以要使用 IS NULL,并且要记住聚合函数会静默跳过 NULL,而 COUNT(*) 不会。面试官会故意埋一个 NULL 来看你是否注意到。在默认值合理的地方使用 COALESCE。

聚合前先去重

如果源数据中有重复事件,对它们求和会夸大总数。先用 DISTINCT 或 ROW_NUMBER = 1 的 CTE 去重,然后再聚合。始终在前后核对行数。

没有内置函数时求中位数或百分位数

如果 PERCENTILE_CONT 不可用,可以用 ROW_NUMBER 和 COUNT 对行排序,然后取中间值。这表明你能从定义出发进行推理,而不只是调用函数。

现在就试一题,无需注册账号

从原始日志统计各服务的错误率

每行日志应形如 "service level message"(三个或更多以空格分隔的部分,其中 level 为 INFO、WARN 或 ERROR)。给定一个列表……

在浏览器中解答 →

编辑器和测试运行器直接在页面中加载。这就是 FDE 编程环节所使用的格式。

在实时 SQL 练习场中免费练习这些题目

常见问题

前沿部署工程师面试中会考哪些 SQL?

针对真实数据模式的多步骤转换:窗口函数(ROW_NUMBER、RANK、SUM/LAG OVER)、连接粒度与反连接、带 HAVING 的 GROUP BY、条件聚合透视,以及同期群或漏斗分析。正确性最重要,尤其要避免在一对多连接中重复计数,并正确处理 NULL 值。

FDE SQL 面试会考窗口函数吗?

会,它们是该环节中最能拉开差距的考点。预计会遇到“每位客户的首笔购买”、累计总额、“每组前 N 名”,以及使用 LAG 计算的环比变化——这些都无法仅靠 GROUP BY 干净地解答。

FDE SQL 环节中最常见的错误是什么?

静默的扇出(fan-out):连接一对多关系时重复计算了某个指标却毫无察觉。解决办法是在连接前先说明每张表的粒度,先在 CTE 中聚合到正确的粒度,并在每一步之后核对行数是否合理。

我该如何为前沿部署工程师面试练习 SQL?

动手编写并运行真实的查询,而不是死记语法。Rung 提供浏览器内的实时 SQL 练习场,题目涵盖从 GROUP BY 到高难度的窗口函数和关联子查询问题,每道题都会与参考结果比对,帮助你快速建立正确的直觉。