← 每日面试题 学习看板

有没有用过窗口函数开窗函数正则表达式在MySQL查询中使用过

面试题/真实面试/2026/有没有用过窗口函数开窗函数正则表达式在MySQL查询中使用过.md

有没有用过窗口函数开窗函数正则表达式在MySQL查询中使用过

首次来源:北京万联易达 2026-01-23 一面

原题

有没有用过窗口函数(开窗函数)?正则表达式在 MySQL 查询中使用过吗?体验如何?

完整讲解(权威版)

最后更新:2026-10-29 · 基于第 1 次作答

L1 · 30 秒速记

结论:窗口函数(ROW_NUMBER/RANK/SUM() OVER)适合报表/排名/去重取最新,MySQL 8.0+ 支持;正则(REGEXP/RLIKE)能表达复杂匹配但性能差,只适合小数据量/离线。 关键词:ROW_NUMBER · RANK · OVER PARTITION · REGEXP · 回表 边界:8.0 以下无窗口函数;大表用窗口函数会全表扫描/排序,性能差,尽量下推到应用或离线。

L2 · 核心讲解

核心考点定位:面试官想确认你是否知道 MySQL 8.0 新增的窗口函数是"分组的进阶"——它不折叠行,每行保留并附加窗口计算值;以及你是否理解正则表达式在 MySQL 中的性能代价,别在业务主链路乱用。

机制链(≥3 环):

  1. 窗口函数执行 → 先分组再逐行计算:为什么,因为 OVER (PARTITION BY ... ORDER BY ...) 定义窗口,对窗口内每行求 ROW_NUMBER/SUM 而不折叠行。
  2. 大表窗口 → 排序/全表扫描成本:为什么,因为窗口函数需要按 ORDER BY 排序并维护窗口,无法走普通索引直接输出。
  3. 正则匹配 → 逐行扫描 + 正则引擎:为什么,因为 REGEXP 无法用普通 B+Tree 索引,需要全表扫描逐行正则求值。
  4. 性能代价 → 决定使用边界:为什么,因为大表/主链路下窗口与正则成本不可接受,应改用应用层或预聚合。

证据锚点(去重 ≥10):

对比与权衡:

实现能力性能适用
窗口函数(8.0+)强(排名/累计/去重)中(需排序)报表、离线、中小表
GROUP BY 聚合折叠行,丢明细好只取汇总值
应用层 Java 处理灵活取决于数据量需分页/流式
REGEXP复杂匹配差(全表扫)小数据量、校验
LIKE '%x%'简单子串差(无前缀索引)简单包含匹配

常见误区:

  1. 错误:窗口函数和 GROUP BY 一样折叠行 → 正确:窗口函数保留每一行,只附加窗口计算值 → 为什么错:混淆"聚合折叠"与"窗口逐行"。
  2. 错误:大表用 REGEXP 没问题 → 正确:正则无法走索引,大表 type=ALL 全表扫描,性能不可接受 → 为什么错:只看功能,不看执行计划。
  3. 错误:MySQL 所有版本都能用窗口函数 → 正确:8.0+ 才有,5.7 需用户变量模拟,性能差 → 为什么错:忽略版本差异。
  4. 错误:正则能替代 LIKE 前缀查询 → 正确:有前缀的 LIKE 'abc%' 可走索引,正则不能 → 为什么错:把正则当万能索引。

适用边界:窗口函数与正则适合离线/报表/小数据量校验,不要放进业务主链路;大表排名用 Redis zset 或预聚合表,正则校验放到应用层或 CHECK 约束小表;8.0 以下无窗口函数需先确认版本。

延伸追问(≥3)

  1. 如何用窗口函数取每个用户最新一条记录?
  1. RANK() 与 DENSE_RANK() 区别?
  1. 为什么正则不能在 MySQL 大表用?

面试者参考回答(400–700 字)

【结论】 窗口函数(ROW_NUMBER/RANK/SUM() OVER)适合报表、排名、取每组最新,MySQL 8.0+ 才有;正则(REGEXP/RLIKE)能表达复杂匹配但性能差,只适合小数据量或离线。

【三点】 第一,窗口函数我用在统计报表:比如取每个用户最新一条订单、算累计占比、排名,用 ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) 加外层 WHERE rn=1,它保留每一行并附加窗口值,不像 GROUP BY 那样折叠行。第二,正则我在校验类场景用过,比如校验字段格式、提取子串(REGEXP_LIKE/REGEXP_SUBSTR),但只在数据量小、离线场景用。第三,体验上最大的教训是性能:窗口函数要排序维护窗口,正则无法走索引、几乎必然 type=ALL 全表扫描,我在早期 ERP 写大 SQL 吃过苦,数据量大后把这类逻辑下推到应用层或预聚合,不让数据库背这种成本。

【边界】 窗口函数 8.0 以下不可用(5.7 需用户变量模拟);大表排名用 Redis zset 或预聚合表,正则放应用层或小表 CHECK,别进业务主链路。

面试记录 2026-10-29(第 1 次)

题目:有没有用过窗口函数开窗函数正则表达式在MySQL查询中使用过

难度:medium

标签:db/mysql/index, real-interview, difficulty/medium

评分:⭐⭐⭐☆☆(3/5)

练习次数:1

我的回答

有用过窗口函数,也用过正则,不过基本上是在统计报表中使用的,不会在业务系统对外的功能中使用,这种东西性能差的有些离谱,一些东西可以在外部通过业务设计实现,不要把压力都抛给数据库,我之前最初的写ERP的时候喜欢写大sql,后来用户量和数据量提高后,吃了很多苦;数据量小的时候用这些东西没问题,数据量大了最好不要在数据库中用这些东西;

点评

优点:立场正确——窗口函数/正则只用于统计报表、避免压给 DB,且有 ERP 大 SQL 的实践教训。

不足:未举具体函数(ROW_NUMBER/RANK/LAG/SUM() OVER、REGEXP_LIKE),体验偏泛,未提 8.0 版本门槛。

补充:窗口函数 8.0+、保留每行不折叠;正则无法走索引、type=ALL 全表扫描;大表排名用 zset/预聚合。

完整讲解见上方「完整讲解(权威版)」