从Rails postgres数据库中删除重复项

时间:2016-05-29 20:44:16

标签: ruby-on-rails ruby postgresql activerecord

我有一个使用Rails应用程序创建的本地PostgreSQL数据库。它有600k的记录,其中约200k是重复的。我想只保留1条记录并删除重复项。我每天都会写SQL来工作,但Rails是我的爱好,我仍然在与ActiveRecord斗争。

以下是我找到重复项的方法(在Rails控制台中):

Summary.select(:map_id).group(:map_id).having("count(*) > 1")

我不认为我可以简单地将destroy_all添加到该语句的末尾,因为它会销毁该条目的所有实例,包括重复值。

你能告诉我如何更新它以便删除重复项吗?

3 个答案:

答案 0 :(得分:2)

我会转到数据库控制台(rails dbconsole)并执行:

SELECT DISTINCT ON (map_id) * FROM summaries AS some_temp_name;

然后重命名表格。

编辑 - 这看起来像你正在寻找的东西:

Summary.where.not(id: Summary.group(:map_id).pluck('min(summaries.id)')).delete_all

未经测试。这是这个答案的一部分: Rails: Delete duplicate records based on multiple columns

答案 1 :(得分:2)

这会破坏wave中的重复项,每次传递时每map_id只选择一个副本。当不再存在重复时,循环将自动完成。

loop do
  duplicates = Summary.select("MAX(id) as id, map_id").group(:map_id).having("count(*) > 1")
  break if duplicates.length == 0
  duplicates.destroy_all
end

如果数据库如下所示:

| id | map_id |
|  1 |    235 |
|  2 |    299 |
|  3 |    324 |
|  4 |    235 |
|  5 |    235 |
|  6 |    299 |
|  7 |    235 |
|  8 |    324 |
|  9 |    299 |

在第一波中,这些记录将被退回并销毁:

| id | map_id |
|  7 |    235 |
|  8 |    324 |
|  9 |    299 |

在第二波中,此记录将被返回并销毁:

| id | map_id |
|  5 |    235 |
|  6 |    299 |

第三波将返回并销毁此记录:

| id | map_id |
|  4 |    235 |

第四次浪潮将完成整个过程。除非给定的map_id有很多重复项,否则这个过程很可能会以一位数的循环迭代完成。

根据该方法,只返回重复项,并且只删除较新的重复项。要删除较旧的重复项,请将查询更改为:

  duplicates = Summary.select("MIN(id) as id, map_id").group(:map_id).having("count(*) > 1")

在这种情况下,wave 1将返回并销毁:

| id | map_id |
|  1 |    235 |
|  2 |    299 |
|  3 |    324 |

第2波将返回并摧毁:

| id | map_id |
|  4 |    235 |
|  6 |    299 |

Wave 3将返回并销毁:

| id | map_id |
|  5 |    235 |

Wave 4将完成整个过程。

答案 2 :(得分:1)

我建议做的是通过具有重复项的字段获取所有记录和订单。

然后循环所有记录,每个值保留一条记录。

value = nil
Summary.order("map_id ASC").each do |record|
  if record.map_id == value
    # duplicate
    record.destroy
  else
    # first entry
    value = record.map_id
  end
end