Was ist der beste Weg, um Datensätze mit doppelten Werten über mehrere Spalten mit Postgres und Activerecord zu finden?
Ich habe diese Lösung gefunden hier :
User.find(:all, :group => [:first, :email], :having => "count(*) > 1" )
Aber es scheint nicht mit Postgres zu funktionieren. Ich erhalte diesen Fehler:
PG :: GroupingError: ERROR: Spalte "parts.id" muss in der GROUP BY-Klausel enthalten sein oder in einer Aggregatfunktion verwendet werden
Getestete und funktionierende Version
User.select(:first,:email).group(:first,:email).having("count(*) > 1")
Dies ist auch ein wenig unabhängig, aber praktisch. Wenn Sie sehen möchten, wie oft die einzelnen Kombinationen gefunden wurden, setzen Sie am Ende .size:
User.select(:first,:email).group(:first,:email).having("count(*) > 1").size
und Sie erhalten ein Ergebnis, das wie folgt aussieht:
{[nil, nil]=>512,
["Joe", "[email protected]"]=>23,
["Jim", "[email protected]"]=>36,
["John", "[email protected]"]=>21}
Ich fand das ziemlich cool und hatte es noch nie gesehen.
Dank an Taryn, dies ist nur eine optimierte Version ihrer Antwort.
Dieser Fehler tritt auf, weil für POSTGRES Gruppierungsspalten in die SELECT-Klausel eingefügt werden müssen.
versuchen:
User.select(:first,:email).group(:first,:email).having("count(*) > 1").all
(Hinweis: nicht getestet, möglicherweise müssen Sie es optimieren)
BEARBEITET, um die ID-Spalte zu entfernen
Wenn Sie die vollständigen Modelle benötigen, versuchen Sie Folgendes (basierend auf der Antwort von @ newUserNameHere).
User.where(email: User.select(:email).group(:email).having("count(*) > 1").select(:email))
Dadurch werden die Zeilen zurückgegeben, bei denen die E-Mail-Adresse der Zeile nicht eindeutig ist.
Ich kenne keinen Weg, dies über mehrere Attribute zu tun.
Erhalten Sie alle Duplikate mit einer Einzelabfrage , wenn Sie PostgreSQL verwenden:
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