valores repetidos registros quitar para encontraron eliminar duplicados duplicadas datos contar condicion con columnas ruby-on-rails-3 activerecord duplicates destroy

ruby-on-rails-3 - repetidos - quitar duplicados excel con condicion



¿Eliminar registros duplicados basados en múltiples columnas? (6)

Para ejecutarlo en una migración, terminé haciendo lo siguiente (basado en la respuesta anterior de @ aditya-sanghi)

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

Estoy usando Heroku para alojar mi aplicación Ruby on Rails y, por una razón u otra, es posible que tenga algunas filas duplicadas.

¿Hay alguna manera de eliminar registros duplicados en base a 2 o más criterios pero mantener solo 1 registro de esa colección duplicada?

En mi caso de uso, tengo una relación de Marca y Modelo para automóviles en mi base de datos.

Make Model --- --- Name Name Year Trim MakeId

Me gustaría eliminar todos los registros del modelo que tienen el mismo nombre, año y recorte, pero guardo 1 de esos registros (es decir, necesito el registro, pero solo una vez). Estoy usando la consola Heroku para poder ejecutar algunas consultas de registro activas fácilmente.

¿Alguna sugerencia?


Puede intentar lo siguiente: (basado en respuestas anteriores)

ids = Model.group(''name, year, trim'').pluck(''MIN(id)'')

para obtener todos los registros válidos Y entonces:

Model.where.not(id: ids).destroy_all

para eliminar los registros innecesarios. Y ciertamente, puede hacer una migración que agregue un índice único para las tres columnas, de modo que esto se aplique en el nivel de la base de datos:

add_index :models, [:name, :year, :trim], unique: true


Puede probar esta consulta SQL, para eliminar todos los registros duplicados, pero el último

DELETE FROM users USING users user WHERE (users.name = user.name AND users.year = user.year AND users.trim = user.trim AND users.id < user.id);


Si los datos de su tabla de usuario son los siguientes

User.all => [ #<User id: 15, name: "a", email: "[email protected]", created_at: "2013-08-06 08:57:09", updated_at: "2013-08-06 08:57:09">, #<User id: 16, name: "a1", email: "[email protected]", created_at: "2013-08-06 08:57:20", updated_at: "2013-08-06 08:57:20">, #<User id: 17, name: "b", email: "[email protected]", created_at: "2013-08-06 08:57:28", updated_at: "2013-08-06 08:57:28">, #<User id: 18, name: "b1", email: "[email protected]", created_at: "2013-08-06 08:57:35", updated_at: "2013-08-06 08:57:35">, #<User id: 19, name: "b11", email: "[email protected]", created_at: "2013-08-06 09:01:30", updated_at: "2013-08-06 09:01:30">, #<User id: 20, name: "b11", email: "[email protected]", created_at: "2013-08-06 09:07:58", updated_at: "2013-08-06 09:07:58">] 1.9.2p290 :099 >

Los ID de correo electrónico están duplicados, por lo que nuestro objetivo es eliminar todos los ID de correo electrónico duplicados de la tabla de usuario.

Paso 1:

Para obtener todos los registros de correo electrónico diferentes.

ids = User.select("MIN(id) as id").group(:email,:name).collect(&:id) => [15, 16, 18, 19, 17]

Paso 2:

Para eliminar identificaciones duplicadas de la tabla de usuario con distintas identificaciones de correo electrónico.

Ahora la matriz ids contiene los siguientes identificadores.

[15, 16, 18, 19, 17] User.where("id NOT IN (?)",ids) # To get all duplicate records User.where("id NOT IN (?)",ids).destroy_all

** RAILS 4 **

ActiveRecord 4 presenta el método .not que le permite escribir lo siguiente en el Paso 2:

User.where.not(id: ids).destroy_all


Similar a la respuesta de @Aditya Sanghi, pero de esta manera será más eficaz porque solo está seleccionando los duplicados, en lugar de cargar todos los objetos del Modelo en la memoria y luego iterar sobre todos ellos.

# 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

Además, si realmente no desea datos duplicados en esta tabla, probablemente desee agregar un índice único de varias columnas a la tabla, algo como:

add_index :models, [:name, :year, :trim], unique: true, name: ''index_unique_models''


class Model def self.dedupe # find all models and group them on keys which should be common grouped = all.group_by{|model| [model.name,model.year,model.trim,model.make_id] } grouped.values.each do |duplicates| # the first one we want to keep right? first_one = duplicates.shift # or pop for last one # if there are any more left, they are duplicates # so delete all of them duplicates.each{|double| double.destroy} # duplicates can now be destroyed end end end Model.dedupe

  • Encuentra todos
  • Agrúpelos en las claves que necesita para la singularidad
  • Bucle en los valores del modelo agrupado del hash
  • elimine el primer valor porque quiere retener una copia
  • elimina el resto