首页 > 数据库 >SQL窗口函数面试题:价值不止于高级写法

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

来源:互联网 2026-07-10 08:29:12

SQL窗口函数的核心价值在于表达分组排序范围内计算的意图,而非炫技。需理解partition、order、frame三个概念。性能上应先缩小数据范围再开窗。连续登录利用日期减排名构造分组键。LAG函数需注意日期连续性。

先说说后端面试里那些绕不开的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:并列怎么处理?

假设工资是 [100, 100, 90]:

row_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;

这道题的关键是:把“连续”这个抽象概念,转成具体的“同组”标识。窗口函数只是帮你实现这个转化的工具,核心洞察才是真正的答案。

还有一个经常被忽略的细节:同一天登录多次,算一次还是多次?题目没说,得先弄清楚去重规则。

同比环比场景下,LAG 函数很常用。它能拿到上一行的数据,但上一行是不是昨天、上周或者上月,取决于排序和数据是否完整。如果日期本身不连续,直接用 LAG 可能拿到一个完全错误的基准。

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

这段代码只适合日期连续的场景。如果日期有空缺,需要先补一张日历表。面试时能指出这个边界条件,会让面试官觉得你考虑得很周全。

总结

SQL 窗口函数的真正价值,在于能够清晰地表达“在分组和排序范围内进行计算”的意图,无论是排名、累计、还是偏移量。重点是把 partitionorderframe 这三个概念理解透,而不是机械地背几个函数名。

窗口函数不是为了写得高级,而是为了把“组内计算”这件事说清楚、写简洁。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备2026025700号-3 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。