webentwicklung-frage-antwort-db.com.de

Suchen Sie mit Active Record, Rails & Postgres nach Zeilen mit mehreren doppelten Feldern

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

77
newUserNameHere

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.

169
newUserNameHere

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

25
Taryn East

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.

6
Ben Aubin

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
0
itsnikolay