SQL 使用窗口函数实现“去重保留最新”

窗口函数“去重保留最新”的核心是按业务主键分组并依时间或ID倒序排序,用ROW_NUMBER()标序后取rn=1;DISTINCT和GROUP BY无法可控留指定记录,而窗口函数可灵活扩展为保留最新N条。

用窗口函数实现“去重保留最新”,核心是先按分组和时间(或序号)排序,再给每组内的记录标序号,最后取每组序号为 1 的那条。

按业务主键分组 + 时间字段倒序

假设有一张用户操作日志表 user_log,含字段:user_idactioncreated_at(时间戳),需对每个 user_id 只保留最新一条记录。

写法如下:

SELECT user_id, action, created_at
FROM (
  SELECT *,
         ROW_NUMBER() OVER (
           PARTITION BY user_id 
           ORDER BY created_at DESC
         ) AS rn
  FROM user_log
) t
WHERE rn = 1;

用 ID 替代时间字段(当无明确时间字段时)

如果表里没有时间字段,但有自增主键 id,且插入顺序与“新旧”逻辑一致,可直接按 id DESC 排序:

  • PARTITION BY user_id 分组
  • ORDER BY id DESC 让最大 ID 排第一
  • ROW_NUMBER() 标出组内顺序,取 rn = 1

注意 DISTINCT 和 GROUP BY 不适用的场景

DISTINCT 只能去完全重复行,无法控制“留哪一条”;GROUP BY 若选非分组字段(如 action)会报错或结果不可控。窗口函数才是可控去重的标准解法。

扩展:保留最新 N 条(比如每人最近 3 次操作)

只需把 WHERE rn = 1 改成 WHERE rn 即可,灵活度高。