SQL面试题:窗口函数的价值不只在于写法高级

作者:袖梨 2026-07-10

后端面试里,SQL 题经常出现:每组取 TopN、连续登录、同比环比、累计求和。很多同学一看到就想上窗口函数,但窗口函数不是为了显得高级,而是为了表达“在某个分组和排序范围内计算”。

SQL面试题:窗口函数的价值,不只在于“写法高级”

会用窗口函数,重点不是背 row_number(),而是知道 partition、order 和 frame 在描述什么。

一、每组 TopN 示例

题目:每个部门取工资最高的 3 个人。

SELECT *FROM (  SELECT employee_id,         department_id,         salary,         ROW_NUMBER() OVER (           PARTITION BY department_id           ORDER BY salary DESC         ) AS rn  FROM employee) tWHERE rn <= 3;

PARTITION BY department_id 表示每个部门单独排名,ORDER BY salary DESC 表示按工资降序。

二、窗口函数执行逻辑

flowchart TD  A[原始数据] --> B[按 partition 分组]  B --> C[组内排序]  C --> D[计算窗口函数]  D --> E[外层过滤]

窗口函数是在结果行上附加计算结果,不会像 group by 那样把多行压成一行。这是它和聚合查询的关键区别。

三、row_number、rank、dense_rank 区别

salary: 100, 100, 90row_number: 1, 2, 3rank:       1, 1, 3dense_rank: 1, 1, 2

是否处理并列,要看业务题意。面试时不要默认用 row_number。题目说“前三名”,并列是否都要保留?要问清楚。

四、性能注意点

窗口函数通常需要排序。大表上要注意分区字段、排序字段、过滤条件。能先过滤日期和业务范围,就不要全表开窗。

WHERE dt = '2026-07-03'

这句简单的分区过滤,可能比你换十种窗口写法都重要。

面试里还常考连续登录。可以用日期减去排名构造分组键,同一段连续日期的差值相同。

SELECT user_id, MIN(login_date), MAX(login_date), COUNT(*)FROM (  SELECT user_id,         login_date,         DATE_SUB(login_date, INTERVAL ROW_NUMBER() OVER (           PARTITION BY user_id ORDER BY login_date         ) DAY) AS grp  FROM user_login) tGROUP BY user_id, grp;

这类题最重要的是把“连续”转成“同组”。窗口函数只是工具,核心观察才是答案。

写 SQL 时也要问清去重规则。同一天登录多次,是算一次还是多次?题目没说,就要先处理。

窗口函数还常用于同比环比。LAG 能拿到上一行,但上一行是否就是昨天、上周、上月,要看排序和数据完整性。日期缺失时,直接 lag 可能拿错基准。

SELECT dt,       gmv,       LAG(gmv, 1) OVER (ORDER BY dt) AS prev_gmvFROM ads_daily_gmv;

这段只适合日期连续的情况。如果日期不连续,要先补日历表。面试里能指出这个边界,会显得很清醒。

五、总结

SQL 窗口函数用于在分组和排序范围内计算排名、累计、偏移等结果。关键是理解 partition、order、frame,而不是背高级语法。

窗口函数不是为了显得高级,是为了把“组内计算”说清楚。

相关文章

精彩推荐