我正在使用Heroku托管我的Ruby on Rails应用程序,由于这样或那样的原因,我可能有一些重复的行。
有没有一种方法可以删除基于2个或更多条件的重复记录,而只保留该重复集合的1条记录?
在我的用例中,我的数据库中有汽车的Make和Model关系。
Make Model
--- ---
Name Name
Year
Trim
MakeId
我想删除所有具有相同名称、年份和修剪的模型记录,但保留其中一条记录(意思是,我只需要一次记录)。我正在使用Heroku控制台,所以我可以轻松地运行一些活动记录查询。
有什么建议吗?
发布于 2016-01-12 15:41:57
类似于@Aditya Sanghi的答案,但这种方式会更有性能,因为您只需要选择副本,而不是将每个Model对象加载到内存中,然后迭代所有这些对象。
# returns only duplicates in the form of [[name1, year1, trim1], [name2, year2, trim2],...]
duplicate_row_values = Model.select('name, year, trim, count(*)').group('name, year, trim').having('count(*) > 1').pluck(:name, :year, :trim)
# load the duplicates and order however you wantm and then destroy all but one
duplicate_row_values.each do |name, year, trim|
Model.where(name: name, year: year, trim: trim).order(id: :desc)[1..-1].map(&:destroy)
end
此外,如果您确实不希望在该表中存在重复数据,则可能需要向该表添加一个多列唯一索引,如下所示:
add_index :models, [:name, :year, :trim], unique: true, name: 'index_unique_models'
发布于 2018-04-07 01:33:51
您可以尝试以下操作:(基于前面的答案)
ids = Model.group('name, year, trim').pluck('MIN(id)')
以获取所有有效记录。然后:
Model.where.not(id: ids).destroy_all
删除不需要的记录。当然,您可以进行迁移,为这三列添加一个唯一索引,以便在DB级别强制执行此操作:
add_index :models, [:name, :year, :trim], unique: true
发布于 2016-03-22 22:25:23
为了在迁移中运行它,我最终执行了如下操作(基于@aditya-sanghi的answer above )
class AddUniqueIndexToXYZ < ActiveRecord::Migration
def change
# delete duplicates
dedupe(XYZ, 'name', 'type')
add_index :xyz, [:name, :type], unique: true
end
def dedupe(model, *key_attrs)
model.select(key_attrs).group(key_attrs).having('count(*) > 1').each { |duplicates|
dup_rows = model.where(duplicates.attributes.slice(key_attrs)).to_a
# the first one we want to keep right?
dup_rows.shift
dup_rows.each{ |double| double.destroy } # duplicates can now be destroyed
}
end
end
https://stackoverflow.com/questions/14124212
复制相似问题