You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL单列去重问题:按ID保留最大day值的唯一行

解决SQL中按ID保留最大day值行的去重问题

问题分析

你的原查询无法去重的核心原因是:当同一个ID存在多条day等于最大值的记录(且这些记录的score不同)时,WHERE day IN (...)会把所有这些行都筛选出来,而DISTINCT无法消除它们——因为这些行的score字段值不同,属于不同的记录。你需要的是每个ID仅保留一条day最大的记录,而非所有day等于最大值的记录。

解决方案

以下是几种通用且高效的实现方式,适用于不同版本的SQL数据库:

方法1:窗口函数ROW_NUMBER()(推荐,支持MySQL 8+、PostgreSQL、SQL Server等)

这是最灵活的方案,能精准控制每个ID取哪一行:

SELECT ID, score, day
FROM (
    SELECT 
        ID, 
        score, 
        day,
        -- 按ID分组,每组内按day降序排序,给行编号
        ROW_NUMBER() OVER (PARTITION BY ID ORDER BY day DESC) AS row_num
    FROM tableA
) AS temp
-- 取每个组的第一行(即day最大的行)
WHERE row_num = 1;
  • 如果同一个ID有多条day为最大值的记录,且你想指定取score最大的那一行,只需修改排序规则:
    ROW_NUMBER() OVER (PARTITION BY ID ORDER BY day DESC, score DESC) AS row_num
    

方法2:关联子查询(兼容MySQL 5.x等不支持窗口函数的版本)

通过子查询先获取每个ID的最大day,再关联原表筛选对应行:

SELECT a.ID, a.score, a.day
FROM tableA a
JOIN (
    SELECT ID, MAX(day) AS max_day
    FROM tableA
    GROUP BY ID
) AS b 
ON a.ID = b.ID AND a.day = b.max_day;
  • 如果同一个ID有多个max_day的记录,需要去重的话,可以结合聚合函数指定score的取值(比如取最大score):
    SELECT a.ID, MAX(a.score) AS score, a.day
    FROM tableA a
    JOIN (
        SELECT ID, MAX(day) AS max_day
        FROM tableA
        GROUP BY ID
    ) AS b 
    ON a.ID = b.ID AND a.day = b.max_day
    GROUP BY a.ID, a.day;
    

方法3:窗口函数FIRST_VALUE()

利用窗口函数直接提取每个ID对应最大day的score:

SELECT DISTINCT
    ID,
    FIRST_VALUE(score) OVER (PARTITION BY ID ORDER BY day DESC) AS score,
    MAX(day) OVER (PARTITION BY ID) AS day
FROM tableA;

原查询问题总结

原查询的逻辑是“筛选所有day等于任意ID最大day的行”,而非“每个ID仅取自己最大day的那一行”——这会导致当某个ID有多条max_day记录时,所有这些行都会被保留,最终出现重复ID的情况。

内容的提问来源于stack exchange,提问作者mapleleaf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 03:52:49