ruby - Cómo encontrar registros que tienen datos duplicados utilizando Active Record
activerecord arel (6)
¿Cuál es la mejor manera de encontrar registros con valores duplicados en una columna usando ruby y el nuevo Activerecord?
Aquí hay una solución que amplía las otras respuestas para mostrar cómo encontrar e iterar a través de los registros agrupados por el campo duplicado:
duplicate_values = Model.group(:field).having(Model.arel_table[:field].count.gt(1)).count.keys
Model.where(field: duplicate_values).group_by(&:field).each do |value, records|
puts "The records with ids #{records.map(&:id).to_sentence} have field set to #{value}"
end
Parece una pena que haya que hacer esto con dos consultas, pero esta respuesta confirma este enfoque.
Así es como lo resolví con los ayudantes de AREL y sin SQL personalizado:
Person.select("COUNT(last_name) as total, last_name")
.group(:last_name)
.having("COUNT(last_name) > 1")
.order(:last_name)
.map{|p| {p.last_name => p.total} }
Realmente, es solo una forma más agradable de escribir el SQL. Encuentra todos los registros que tienen valores de last_name duplicados y te dice cuántos y cuáles son los apellidos en un buen hash.
Con SQL personalizado, encuentra types
con los mismos valores para el name
:
sql = ''SELECT id, COUNT(id) as quantity FROM types
GROUP BY name HAVING quantity > 1''
repeated = ActiveRecord::Base.connection.execute(sql)
En Rails 2.x, seleccione es un método privado de clase AR. Solo usa find ():
klass.find(:all,
:select => "id, count(the_col) as num",
:conditions => ["extra conditions here"],
:group => ''the_col'',
:having => "num > 1")
Me estaba golpeando la cabeza contra este problema con una pila de 2016 (Rails 4.2, Ruby 2.2), y obtuve lo que quería con esto:
> Model.select([:thing]).group(:thing).having("count(thing) > 1").all.size
=> {"name1"=>5, "name2"=>4, "name3"=>3, "name4"=>2, "name5"=>2}
Traduciendo @TuteC en ActiveRecord:
sql = ''SELECT id,
COUNT(id) as quantity
FROM types
GROUP BY name
HAVING quantity > 1''
#=>
Type.select("id, count(id) as quantity")
.group(:name)
.having("quantity > 1")