如何编写MySQL查询实现user_name与year_taken双列去重?
按两列去重获取用户每年一条考试记录的MySQL查询方法
要实现按user_name和year_taken两列去重,每个用户每年仅保留一条考试记录,有两种实用方案,可根据你的MySQL版本和需求选择:
方案一:使用窗口函数(MySQL 8.0+ 推荐)
这种方法能精确控制保留哪条记录(比如最早考试、最高分等),且能完整保留该行所有字段,完全匹配你的示例需求:
SELECT user_name, test_taken, score, year_taken FROM ( SELECT user_name, test_taken, score, year_taken, -- 按「用户+年份」分组,每组内按考试编号升序标记序号,取第一条 ROW_NUMBER() OVER (PARTITION BY user_name, year_taken ORDER BY test_taken ASC) AS rn FROM your_table_name -- 替换为你的实际表名 ) AS sub_query WHERE rn = 1;
说明:
PARTITION BY user_name, year_taken:将数据按用户和年份的组合分组ORDER BY test_taken ASC:每组内按考试编号从小到大排序,确保最早的考试记录被标记为rn=1- 如果想保留用户每年的最高分记录,只需把
ORDER BY test_taken ASC改成ORDER BY score DESC即可
方案二:使用GROUP BY(兼容低版本MySQL)
若你的MySQL版本低于8.0,不支持窗口函数,可以用GROUP BY结合聚合函数实现,但需要明确字段的聚合规则:
SELECT user_name, MIN(test_taken) AS test_taken, -- 取每组最小的考试编号 -- 通过子查询关联,获取该考试编号对应的分数,保证字段匹配准确 (SELECT score FROM your_table_name t2 WHERE t2.user_name = t1.user_name AND t2.year_taken = t1.year_taken AND t2.test_taken = MIN(t1.test_taken)) AS score, year_taken FROM your_table_name t1 GROUP BY user_name, year_taken;
说明:
- 这里用
MIN(test_taken)确定要保留的考试记录,再通过子查询拉取对应分数,避免聚合函数导致的字段不匹配问题 - 也可根据需求替换聚合逻辑,比如用
MAX(score)直接取每年最高分,但这种方式无法保证分数对应特定的考试编号
内容的提问来源于stack exchange,提问作者Log
相关产品推荐
相关产品推荐

