当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL 窗口函数按时间去重时如何保留最新行

MySQL 窗口函数按时间去重时如何保留最新行

来源:17golang原创 2026-09-15 07:09:41 0浏览 收藏

日志表、订单状态表、同步快照表经常会出现同一个业务键的多条记录。要按时间去重并保留最新行,最稳妥的写法是:用 ROW_NUMBER() 在每个业务分组内按时间倒序编号,再在外层筛选 rn = 1。不要直接用 GROUP BY 配合 MAX(updated_at),那样很容易丢掉与最新时间对应的其他列。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/window-functions-usage.html

要点速览
  • PARTITION BY 决定“同一组”是什么,ORDER BY 决定哪一行排在最前。
  • 时间相同时追加唯一键倒序,避免同一批数据每次返回不同记录。
  • 窗口函数结果要放进 CTE 或派生表,再由外层过滤 rn = 1

先把“同一条记录”和“最新”定义清楚

我处理这类数据时,第一步不是写 SQL,而是先确认去重键。例如一个账号下同一个业务编码只能留一行,就用 account_id, biz_key 作为分组键;如果同一编码在不同租户之间互不相同,还必须把 tenant_id 加进去。分组键少了,会把本不该合并的记录删掉。

“最新”通常对应 updated_at,但创建时间、采集时间、状态生效时间的含义并不一样。还要确认它是否允许 NULL,以及精度是否只有秒级。如果多个记录共享同一个时间,必须准备一个唯一且稳定的次排序列,常见的是自增 id

用 ROW_NUMBER() 给每个分组排出第一行

下面的例子按账号和业务键去重,保留更新时间最大的完整记录。窗口函数本身仍会为每一行产生结果,所以先在 CTE 中增加序号,再从外层取第一行。

WITH ranked AS (
  SELECT
    id, account_id, biz_key, updated_at, payload,
    ROW_NUMBER() OVER (
      PARTITION BY account_id, biz_key
      ORDER BY updated_at DESC, id DESC
    ) AS rn -- 时间相同则用唯一 id 稳定决胜
  FROM activity_log
)
SELECT id, account_id, biz_key, updated_at, payload
FROM ranked
WHERE rn = 1; -- 外层过滤,保留每组排名第一的完整行

PARTITION BY 只负责划分窗口,不会像 GROUP BY 那样把行合并;ORDER BY updated_at DESC 让最新时间排在前面,id DESC 则处理同一时间的并列。MySQL 手册也明确说明,ROW_NUMBER() 在没有排序时编号是不确定的,因此不要省略窗口内的排序。

MySQL ROW_NUMBER 按 account_id 和 biz_key 分组并连接更新时间与唯一 id 的静态查询结构图
图1:MySQL 去重查询结构示意图;业务键进入分组边界,更新时间和唯一 id 共同决定组内的稳定排序。

并列时间、NULL 和性能取舍要单独处理

如果只写 ORDER BY updated_at DESC,同一组里时间相同的行都是并列项,数据库没有义务替你选择固定的一行。追加 id DESC 后,规则就变成“时间更新者优先,时间相同取 id 较大者”。如果业务上不允许任意决胜,则应增加版本号或明确的生效序列,而不是把选择交给执行计划。

降序排序时 NULL 的位置也要确认。MySQL 中升序 NULL 排在前面,降序 NULL 排在后面;如果 NULL 代表“未知”而不是“最旧”,可以显式写出业务规则,例如用 CASE WHEN updated_at IS NULL THEN 1 ELSE 0 END 作为首个排序表达式,并在注释中说明原因。

数据量较大时,窗口排序仍可能需要处理大量候选行。先用明确的时间范围、租户条件或状态条件缩小输入,再观察 EXPLAIN,通常比盲目添加索引更可靠。索引列顺序要围绕真实过滤条件和分组键设计,不能因为查询里出现了 ORDER BY 就假设一定可以完全避免排序。

MySQL 去重结果中的业务键、更新时间、唯一 id、CTE 序号和 rn 等于 1 的静态关系图
图2:最新行保留边界示意图;并列决胜、NULL 规则和外层 rn=1 共同决定最终留下哪条完整记录。

上线前用四项检查确认结果

检查项要确认的内容
分组键是否包含租户、账号和业务对象的全部唯一维度
时间字段是否真代表最新状态,时区、精度和 NULL 语义是否明确
并列规则是否有唯一键、版本号或业务序列作为次排序
结果复核随机抽取一个分组,检查留下的行确实对应最大时间及决胜列

如果只是展示最新状态,这个查询通常足够;如果要把去重结果写回新表或删除历史行,则应先备份、统计重复组数量,并把写操作放到可回滚的变更流程里。

常见问题

为什么不能直接用 MAX(updated_at)?

MAX() 只能得到最大时间,不能自动带回该时间对应的完整行;窗口编号可以保留整行字段。

ROW_NUMBER() 和 RANK() 怎么选?

要每组严格保留一行,用 ROW_NUMBER();如果并列记录都应该保留,再考虑 RANK()DENSE_RANK()

为什么 rn 不能直接写在 WHERE 里?

窗口函数在当前查询层生成结果,先放入 CTE 或派生表,再由外层按 rn 过滤,边界最清楚。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
墨刀AI批量整理相似需求PRD怎么避免重复?先建公共章节再写差异墨刀AI批量整理相似需求PRD怎么避免重复?先建公共章节再写差异
上一篇
墨刀AI批量整理相似需求PRD怎么避免重复?先建公共章节再写差异
Go channel 只接收方向为什么不能 close
下一篇
Go channel 只接收方向为什么不能 close
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    31次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    132次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    68次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    24次使用
  • CMMLU中文大模型评估基准:功能、使用教程与应用场景解析
    CMMLU
    深入了解CMMLU中文评估基准,涵盖67个学科主题,提供数据集下载、Zero-shot/Five-shot评估方法及排行榜,助力优化中文语言模型性能。
    14次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码