SQL 面试题:窗口函数的价值,不只在于“写法高级”
后端面试里,SQL 题经常出现:每组取 TopN、连续登录、同比环比、累计求和。很多同学一看到就想上窗口函数,但窗口函数不是为了显得高级,而是为了表达“在某个分组和排序范围内计算”。
会用窗口函数,重点不是背 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
) t
WHERE 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, 90 row_number: 1, 2, 3 rank: 1, 1, 3 dense_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
) t
GROUP BY user_id, grp;这类题最重要的是把“连续”转成“同组”。窗口函数只是工具,核心观察才是答案。
写 SQL 时也要问清去重规则。同一天登录多次,是算一次还是多次?题目没说,就要先处理。
窗口函数还常用于同比环比。LAG 能拿到上一行,但上一行是否就是昨天、上周、上月,要看排序和数据完整性。日期缺失时,直接 lag 可能拿错基准。
SELECT dt,
gmv,
LAG(gmv, 1) OVER (ORDER BY dt) AS prev_gmv
FROM ads_daily_gmv;
这段只适合日期连续的情况。如果日期不连续,要先补日历表。面试里能指出这个边界,会显得很清醒。
五、总结
SQL 窗口函数用于在分组和排序范围内计算排名、累计、偏移等结果。关键是理解 partition、order、frame,而不是背高级语法。
窗口函数不是为了显得高级,是为了把“组内计算”说清楚。
到此这篇关于SQL 面试题:窗口函数的价值,不只在于“写法高级”的文章就介绍到这了,更多相关sql窗口函数面试题内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
关于SQL中CTE(公用表表达式)(Common Table Expression)的总结
WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到2012-08-08


最新评论