MySQL如何按card_id去重并返回对应唯一id?
问题描述
当前使用查询语句:SELECT id, card_id FROM sp_answered,该语句会基于id和card_id两列返回去重结果。我需要实现按card_id去重,但返回每个唯一card_id对应的id值,用于其他查询。曾尝试使用group by,但该语句需要配合聚合函数,结合having也无法解决问题。
示例表sp_answered数据如下:
table: sp_answered +-------+-----------+-----------+ | id | card_id | answer | +-------+-----------+-----------+ | 1 | 110 | Answer 1 | | 2 | 111 | Answer 2 | | 3 | 112 | Answer 3 | | 4 | 111 | Answer 4 | | 5 | 114 | Answer 5 | | 6 | 115 | Answer 6 | | 7 | 111 | Answer 7 | | 8 | 117 | Answer 8 | | 9 | 111 | Answer 9 | | 10 | 111 | Answer 10 | +-------+-----------+-----------+
可以看到card_id为111的记录存在重复。执行SELECT DISTINCT card_id FROM sp_answered的结果如下:
table: sp_answered +------------+ | card_id | +------------+ | 110 | | 111 | | 112 | | 114 | | 115 | | 117 | +------------+
但我需要按card_id去重后返回对应的id值,预期结果如下(注:原预期结果表头有误,应为id):
+----+ | id | +----+ | 1 | | 2 | | 3 | | 5 | | 6 | | 8 | +----+
解决方案
方法1:GROUP BY 配合 MIN() 聚合函数
这是最直接的方案,通过GROUP BY card_id分组,用MIN(id)获取每个分组中最小的id(匹配你的预期结果):
SELECT MIN(id) AS id FROM sp_answered GROUP BY card_id;
执行后将得到每个唯一card_id对应的最小id值,完全符合需求。
方法2:窗口函数 ROW_NUMBER()
如果需要更灵活的规则(比如取每个card_id对应的最大id),可以用窗口函数给每个card_id分组内的记录排序,再筛选出第一条:
SELECT id FROM ( SELECT id, ROW_NUMBER() OVER (PARTITION BY card_id ORDER BY id ASC) AS rn FROM sp_answered ) t WHERE rn = 1;
若要取最大id,只需将ORDER BY id ASC改为ORDER BY id DESC即可。
方法3:关联子查询
通过子查询先找出每个card_id对应的最小id,再关联原表获取数据:
SELECT a.id FROM sp_answered a INNER JOIN ( SELECT card_id, MIN(id) AS min_id FROM sp_answered GROUP BY card_id ) b ON a.card_id = b.card_id AND a.id = b.min_id;
补充说明
你之前使用GROUP BY时遇到的问题,是因为没有搭配合适的聚合函数。MIN(id)属于聚合函数,它能从每个card_id分组中提取最小的id值,完全满足你的需求。
内容的提问来源于stack exchange,提问作者Henry Obiaraije
相关产品推荐
相关产品推荐

