2016-04-18 10 views
1

Gegeben eine Klasse, möchte ich alle Objekte (index) nach der Anzahl der Verbände, die sie mit einem bestimmten Attribut haben, zurückgeben.Count Vereinigungen basierend auf Attributwert

Zum Beispiel, lassen Sie uns User has_many :fish sagen, dass ich eine Liste aller Benutzer angezeigt werden sollen und um sie durch wie viele :fish sie haben, die color: :red (Unter der Annahme, das ist eine Enumeration/Integer-Wert)

Benutzer mit 0 roten Fisch, oder 0 Fische überhaupt, sollte noch auf dem Tisch gezeigt werden, aber nach unten sortiert.

-- User -- | - # of fish - | - # of red fish - 
    2  |  10  |  10 
    5  |  25  |   7 
    6  |  11  |   6 
    7  |  18  |   5 
    1  |  27  |   4 
    3  |  23  |   1 
    4  |  3  |   0 
    8  |  0  |   0 

Bisher habe ich es geschafft, die Benutzer durch die Anzahl der Fische sortieren sie mit dem left_join Juwel, aber ich habe Probleme auf diesem Modell durch ein Attribut zu sortieren. Diese

ist, wie ich durch die Anzahl der Fische am Sortierung:

@users = User.left_join(:fish).group("user.id").order("count(user.id) desc")

Jede Hilfe wäre genial! Ich gehe davon aus, dass das trivial ist, aber ich zeige auch diese Daten, also wäre jeder Weg, diese Daten vorübergehend zu speichern, auch toll! (Ich gehe davon aus einer select verwenden und die Einstellung der Zählungen als Variablen)

EDIT:

Lösung dank Anthony E.

@users = User.select("users.*") 
      .joins("LEFT JOIN fishes ON fishes.user_id = users.id") 
      .where(fishes: { color: Fish.colors[:red] }) 
      .group("users.id").order("COUNT(fishes.id) DESC") 
      .page(params[:page]) // To work with Kaminari/pagination 

Antwort

1

Wie wäre:

User.select("user.*, COUNT(fish.id) AS fish_count") 
     .joins(:fish) 
     .where(fish: { color: "red" }) 
     .group("user.id") 
     .order("fish_count DESC") 

Der Vorteil ist, dass Sie fish_count für jedes Objekt in der zurückgegebenen zurückgegebenen Sammlung aufrufen können, weil es in Ihrem ist select

EDIT

Um Benutzer mit 0 Fisch enthalten, verwenden Sie einen LEFT JOIN und ändern Sie die where-Klausel:

User.select("user.*, COUNT(fish.id) AS fish_count") 
     .joins("LEFT JOIN ON fish.user_id = user.id") 
     .where("fish.color = 'red' OR fish.color IS NULL") 
     .group("user.id") 
     .order("fish_count DESC") 
+0

Dies wirft eine 'PG :: UndefinedTable' Fehler in dem Fall, in dem ein Benutzer hat 0 Fische. (Ich glaube, das passiert wegen der 'count' im' select') – Rockster160

+0

Das ist seltsam, Benutzer ohne Fisch sollten über die 'joins'-Klausel ausgeschlossen werden. Deine Tabellennamen sind 'user' und' fish', richtig? Wenn Sie '.where.not (fish: {user_id: nil})' nach der Funktion 'joins (: fish)' hinzufügen, besteht das Problem weiterhin? –

+0

Das Ausschließen von ihnen wäre ein Problem unabhängig davon - es soll immer noch alle Benutzer unabhängig von ihrer Anzahl an Fischen zeigen, einfach nach ihrer Anzahl an Fischen sortiert. (Deshalb habe ich 'left_join' anstelle von' joins' verwendet) - obwohl du Recht hast. Ich bin mir nicht sicher, warum das ein Problem aufwirft. – Rockster160

Verwandte Themen