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

用窗口函数实现“去重保留最新”,核心是先按分组和时间(或序号)排序,再给每组内的记录标序号,最后取每组序号为 1 的那条。
按业务主键分组 + 时间字段倒序
假设有一张用户操作日志表 user_log,含字段:user_id、action、created_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 即可,灵活度高。










