MySQL窗口函数太实用了,轻松应对复杂查询

  • 时间:2025-12-08 22:55 作者: 来源: 阅读:0
  • 扫一扫,手机访问
摘要:想把一堆通用 SQL 任务直接套到自己业务里?可以,别慌。把表名、字段名和业务参数一换,这些模板基本都能跑起来。下面把常见的需求拆开讲清楚,照着做别漏了坑。先说要办的事儿:按部门分组,部门内部按工资从高到低排队,允许并列(工资一样就并列第几);按区域和月份分组,统计每组里销售额排在前三的产品,遇到并列也得并列,但最多只想拿三条;按日期排序,算每天的销售额并累加到当日(可以按区域分区做累计);查每个

想把一堆通用 SQL 任务直接套到自己业务里?可以,别慌。把表名、字段名和业务参数一换,这些模板基本都能跑起来。下面把常见的需求拆开讲清楚,照着做别漏了坑。

MySQL窗口函数太实用了,轻松应对复杂查询

先说要办的事儿:按部门分组,部门内部按工资从高到低排队,允许并列(工资一样就并列第几);按区域和月份分组,统计每组里销售额排在前三的产品,遇到并列也得并列,但最多只想拿三条;按日期排序,算每天的销售额并累加到当日(可以按区域分区做累计);查每个员工的工资,同时把他所在部门的平均工资和差额也显示出来;查每日销售并把前一天和后一天的数拉出来,用来算环比;按部门分组,计算员工在部门里的入职先后顺序,入职早的排在前面;查每个用户的首单和最后一单的时间及金额;按日期排序计算每天及前6天的平均销售(滑动窗口7天);把产品按销售额分为三档(高、中、低),大体各占三分之一;按部门分组,筛出每个部门薪资排名前20%的员工(按比例筛选)。

这些场景里,窗口函数是主角。遇到排序和排名的,就看分区函数。需要保证序号不重复、强制一一对应,就用 ROW_NUMBER;要保留并列但保留跳号就用 RANK(举个例子:1,2,2,4);想保并列但不跳号,就用 DENSE_RANK(看起来像 1,2,2,3);要把数据平均分成几组,NTILE 最方便。做累计或者滑动平均,SUM、AVG、MAX、MIN 可以配合窗口来用。要拿上一条或下一条记录,LAG 和 LEAD 一把抓。要拿分区里第一条或最后一条,FIRST_VALUE、LAST_VALUE 很直接。

具体到几个常见的重点场景,讲清楚怎么处理比较好理解。部门内排名并允许并列,一般就是先在分区里用 DENSE_RANK 或 RANK 标记名次,再按名次过滤。两个人并列第2时,业务上你是要看到 1,2,2,4 还是 1,2,2,3,这个要跟业务确认;差别会影响后面筛出来的结果。按区域和月份取前三名这事儿,有些麻烦:遇到并列会导致返回行数超过 3 条,这就要看业务规则是按“名次<=3”还是“最多返回3行”。常见做法是先用 RANK/DENSE_RANK 标注,再在外层按需裁剪,有时候还得在业务层限制条数。

按日期做累计销售,先把每天的销售聚合出来(按日期聚合),再在这个结果上用窗口做累加,分区字段可以是区域。滑动窗口的平均值,窗口大小设为 7 天,要么按行数要么按日期范围,注意有些数据库对范围支持不一样。算环比时,把当天金额和 LAG(amount,1)、LEAD(amount,1) 拉出来,用这些值去算增长。要小心日期断档,LAG 会返回 NULL,要决定是填 0 还是保 NULL。

查首单和末单,既可用 FIRST_VALUE/LAST_VALUE,也能用 group by + min/max。按照入职顺序排队,常见做法是在部门分区里按入职日期排序,然后用 ROW_NUMBER 或 RANK 得到序号。

把产品按销售分成三档,NTILE(3) 最直接,但边界上销售额一样会让分组不均匀,这需要接受或再做业务规则调整。筛选每个部门前20% 的员工,NTILE 也能派上用场,或者先计算部门总人数乘以 0.2 得到阈值,再筛。

实施细节里要注意的事不算少。分组字段和排序字段要统一格式,像按月统计就把日期修成 YYYY-MM 或用 date_trunc,别让格式不一致把数据分歧。按日期累加要思考是否有断日,缺日要不要补齐,是用 NULL 还是前向填充,要提前定好。关于并列和限制条数,先把“按名次限制”或“按行数限制”搞清楚,不然同样的 SQL 在不同规则下会有天壤之别。把排名逻辑放在子查询或 CTE 里更直观:先标记名次或组别,外层再筛选或聚合,调试时也方便。

性能方面也有套路。遇到慢的情况,先做分组聚合再做窗口运算,往往比对原始明细直接做窗口快。常用分区字段建索引或者用物化视图,也是常见的办法。别把示例 SQL 直接丢进生产库跑,先替换表名、字段名、日期格式、Top N 数量这些业务参数,再跑。

还有几条小提醒:按区域和月份分组的时候,月份字段要统一,别有 2023-3 和 2023-03 这样的差别;LAG/LEAD 拉不到值会返回 NULL,要在外层处理空值;并列名次可能让返回行数超过预期,业务要先确认到底想怎样处理。最后一句话,模板拿来可以直接复制,但务必把表名、字段名、日期格式和 Top N 数量这些位子换成你自个儿的业务参数,跑之前再核一遍字段类型和索引。

  • 全部评论(0)
最新发布的资讯信息
【系统环境|】Linux 安全审计工具 Auditd(2025-12-08 23:24)
【系统环境|】使用Supervisor守护PHP进程:告别手动重启,实现自动化运维(2025-12-08 23:24)
【系统环境|】golang高性能日志库zap的使用(2025-12-08 23:24)
【系统环境|】MySQL主从复制技术详解(2025-12-08 23:24)
【系统环境|】华为MagicBook锐龙版双系统折腾记六:matlab(2025-12-08 23:24)
【系统环境|】ArrayFire:C++高性能张量计算的极速引擎(2025-12-08 23:24)
【系统环境|】一文读懂回声消除(AEC)(2025-12-08 23:23)
【系统环境|】缺人!泰达这些企业招聘!抓紧!(2025-12-08 23:23)
【系统环境|】RS485 Modbus 超级简单轮询程序(2025-12-08 23:23)
【系统环境|】RS485接口≠Modbus协议!工业通信常见认知陷阱(2025-12-08 23:23)
手机二维码手机访问领取大礼包
返回顶部