Quel est le meilleur moyen de rechercher des enregistrements avec des valeurs en double dans une colonne à l'aide de Ruby et du nouvel Activerecord?
Traduire @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")
Voici comment j'ai résolu le problème avec les assistants AREL et aucun SQL personnalisé:
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} }
Vraiment, c'est juste une façon plus agréable d'écrire le code SQL. Cela permet de rechercher tous les enregistrements ayant des valeurs nom_fichier en double et d’indiquer le nombre et le nom des derniers noms dans un hachage Nice.
Je battais la tête contre ce problème avec un stack de 2016 (Rails 4.2, Ruby 2.2), et j'ai obtenu ce que je voulais avec ceci:
> Model.select([:thing]).group(:thing).having("count(thing) > 1").all.size
=> {"name1"=>5, "name2"=>4, "name3"=>3, "name4"=>2, "name5"=>2}
Avec SQL personnalisé, ceci trouve types
avec les mêmes valeurs pour name
:
sql = 'SELECT id, COUNT(id) as quantity FROM types
GROUP BY name HAVING quantity > 1'
repeated = ActiveRecord::Base.connection.execute(sql)
Dans Rails 2.x, select est une méthode privée de la classe AR. Il suffit d'utiliser find ():
klass.find(:all,
:select => "id, count(the_col) as num",
:conditions => ["extra conditions here"],
:group => 'the_col',
:having => "num > 1")
Voici une solution qui étend les autres réponses pour montrer comment rechercher et parcourir les enregistrements groupés par le champ en double:
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
Il semble dommage que cela doive être fait avec deux requêtes mais cette réponse confirme cette approche.