MySQL结果去重:单列值重复时仅保留一行(SQL/Rails方案)
如何在MySQL和Rails中对指定列去重并保留唯一行?
我之前处理过类似的去重需求,给你整理了两种实用方案,分别对应原生MySQL和Rails ActiveRecord的实现,刚好匹配你的需求:
方案一:原生MySQL实现
方法1:GROUP BY + 关联查询(适合指定保留行规则的场景)
如果想保留每个addr分组中id最小的那一行(和你示例的预期结果一致),可以先通过分组找到每个addr对应的最小id,再关联原表获取完整行数据:
SELECT t.id, t.name, t.addr, t.add_id FROM ( SELECT addr, MIN(id) AS min_id FROM your_table_name -- 替换成你的实际表名 GROUP BY addr ) AS sub JOIN your_table_name t ON t.id = sub.min_id;
如果想保留id最大的行,只需把MIN(id)改成MAX(id)即可。
方法2:窗口函数(更灵活的排序规则)
MySQL 8.0及以上版本支持窗口函数,这种方法可以自定义分组内的排序规则,比如按id升序取第一行:
SELECT id, name, addr, add_id FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY addr ORDER BY id ASC) AS row_num FROM your_table_name -- 替换成你的实际表名 ) AS sub WHERE sub.row_num = 1;
如果需要调整保留的行,修改ORDER BY后的字段即可(比如按add_id降序排序)。
方案二:Rails ActiveRecord实现
方法1:对应GROUP BY关联查询的写法
假设你的模型名为YourModel(表名默认是your_models),可以用ActiveRecord拼接子查询:
# 先获取每个addr对应的最小id subquery = YourModel.select(:addr, 'MIN(id) AS min_id').group(:addr) # 关联原表获取完整数据 unique_records = YourModel.joins("JOIN (#{subquery.to_sql}) AS sub ON your_models.id = sub.min_id") .select('your_models.id, your_models.name, your_models.addr, your_models.add_id')
方法2:窗口函数的ActiveRecord写法
同样利用子查询实现窗口函数逻辑:
# 给每条数据添加分组内的行号 subquery = YourModel.select('*, ROW_NUMBER() OVER (PARTITION BY addr ORDER BY id ASC) AS row_num') # 筛选出每组的第一行 unique_records = YourModel.from("(#{subquery.to_sql}) AS sub") .where('sub.row_num = 1') .select('sub.id, sub.name, sub.addr, sub.add_id')
说明:如果是使用PostgreSQL的Rails项目,还可以用distinct_on语法更简洁,但MySQL不支持该特性,所以上面的两种方法更通用。
内容的提问来源于stack exchange,提问作者ZZzzZZzz
相关产品推荐
相关产品推荐

