Rails(或者可能是SQL):查找和删除重复的AR对象

时间:2009-04-13 13:21:25

标签: sql mysql ruby-on-rails ruby activerecord

类'Location'的ActiveRecord对象(表示db-table Locations)具有'url','lat'(纬度)和'lng'(经度)属性。

此模型上的Lat-lng组合应该是唯一的。问题是,数据库中有很多位置对象具有重复的lat-lng组合。

我在执行以下操作时需要帮助

  1. 查找共享相同的对象 纬度和经度组合。
  2. 如果是对象的'url'属性 不为空,保留此对象并删除 其他重复。否则只需选择 最旧的对象(通过检查属性 'created_at')并删除其他重复项。
  3. 由于这是一次性操作,因此欢迎SQL(MySQL 5.1兼容)中的解决方案。

2 个答案:

答案 0 :(得分:5)

如果这是一次性的事情,那么我只是在Ruby中做,而不是太担心效率。我没有对此进行彻底测试,检查排序等,以确保它在您的数据库上运行之前完全符合您的要求:)

keep = []
locations = Location.find(:all)

locations.each do |loc|
  # get all Locations's with the same coords as this one
  same_coords = locations.select { |l| l.lat == loc.lat and \
                                       l.lng == loc.lng }
  with_urls = same_coords.select { |l| !l.url.empty? }

  # decide which list to use depending if there were any urls
  same_coords = with_urls.any? ? with_urls : same_coords

  # pick the best one
  keep << same_coords.sort { |a,b| b.created_at <=> a.created_at }.first.id
end

# only keep unique ids
keep.uniq!

# now we just delete all the rows we didn't decide to keep
locations.each do |loc|
  loc.destroy unless keep.include?( loc.id )
end

就像我说的那样,这绝对是糟糕的,糟糕的代码。但是,有时只是破解有效的东西值得花时间思考“更好”的东西,特别是如果它只是一次性的。

答案 1 :(得分:0)

如果您有2个MySQL列,则可以使用CONCAT功能。

SELECT * FROM table1 GROUP BY CONCAT(column_lat, column_lng)

如果你需要知道总数

SELECT COUNT(*) AS total FROM table1 GROUP BY CONCAT(column_lat, column_lng)

或者,您可以将两者结合起来

SELECT COUNT(*) AS total, table1.* FROM table1 
GROUP BY CONCAT(column_lat, column_lng)

但如果你能对你的问题解释得更多,也许我们可以得到更多相关答案。