Quel est le meilleur moyen de trouver des enregistrements avec des valeurs en double sur plusieurs colonnes à l'aide de Postgres et d'Activerecord?
J'ai trouvé cette solution ici :
User.find(:all, :group => [:first, :email], :having => "count(*) > 1" )
Mais cela ne semble pas fonctionner avec postgres. Je reçois cette erreur:
PG :: GroupingError: ERROR: la colonne "parties.id" doit apparaître dans la clause GROUP BY ou être utilisée dans une fonction d'agrégat
Version testée & de travail
User.select(:first,:email).group(:first,:email).having("count(*) > 1")
En outre, ceci est un peu sans rapport, mais pratique. Si vous voulez voir combien de fois chaque combinaison a été trouvée, mettez .size à la fin:
User.select(:first,:email).group(:first,:email).having("count(*) > 1").size
et vous obtiendrez un résultat en retrait qui ressemble à ceci:
{[nil, nil]=>512,
["Joe", "[email protected]"]=>23,
["Jim", "[email protected]"]=>36,
["John", "[email protected]"]=>21}
Je pensais que c'était plutôt cool et je ne l'avais jamais vu auparavant.
Merci à Taryn, il ne s'agit que d'une version modifiée de sa réponse.
Cette erreur se produit car POSTGRES nécessite que vous placiez des colonnes de regroupement dans la clause SELECT.
essayer:
User.select(:first,:email).group(:first,:email).having("count(*) > 1").all
(note: non testé, vous devrez peut-être le modifier)
EDITED pour supprimer la colonne id
Si vous avez besoin des modèles complets, essayez ce qui suit (basé sur la réponse de @ newUserNameHere).
User.where(email: User.select(:email).group(:email).having("count(*) > 1").select(:email))
Cela renverra les lignes où l'adresse électronique de la ligne n'est pas unique.
Je ne suis pas au courant d'un moyen de faire cela sur plusieurs attributs.
Obtenez tous les doublons avec une requête single si vous utilisez PostgreSQL:
def duplicated_users
duplicated_ids = User
.group(:first, :email)
.having("COUNT(*) > 1")
.select('unnest((array_agg("id"))[2:])')
User.where(id: duplicated_ids)
end
irb> duplicated_users