2011-01-13 3 views
2

Ich habe die folgenden Fragen, aber ich bin mir sicher, dass dies nicht DRY ist. Allerdings kann ich nicht herausfinden, wie man durch die Deals var filtert, anstatt für jede var erneut abzufragen. Ist es möglich?Wie suche ich durch Abfrage Ergebnisse, um zu verhindern, dass viele Anfragen

deals = Deal.all 
won = Deal.find(:all, :conditions => ["status = 'won'"]).count 
pending = Deal.find(:all, :conditions => ["status = 'pending'"]).count 
lost = Deal.find(:all, :conditions => ["status = 'lost'"]).count 

Antwort

5

Verwenden GROUP BY SQL-Klausel:

Hash[Deal.all(:select => 'status, count(*) as count', :group => 'status').map{|e| 
    [e.status, e.count] 
}] 

Edit: Ich habe vergessen, dass Sie bereits alle Datensätze geladen haben. In diesem Fall können Sie Zählungen pro Status erhalten auf diese Weise:

Hash[deals.group_by(&:status).map{|k,v| [k,v.count]}] 
+0

Dieser ist schön! Nur eine mögliche Verbesserung kann ich finden, wenn es die bereits definierten var deals verwenden könnte. Würde es das nicht noch besser machen? (Nettes konzeptionelles Denken auch hier, gut, um diese Art von Lösungen zu sehen :-)) –

+1

Sie haben Recht, ich habe diesen Teil vermisst. Ich habe die Antwort bearbeitet. –

+0

Schön! Klappt wunderbar! Danke vielmals! –

0

Ich glaube, Sie Rubys Inject-Funktion für diese verwenden:

won = deals.inject(0) {|total, deal| deal.status == 'won' ? total + 1 : total } 
+1

Ich dachte über diese Art von Lösung nach, aber ich denke, das ist keine gute Idee, im Grunde definiert dies count(). –

+0

Guter Punkt. Die Datenbank mit der Zählung umgehen zu lassen, ist wahrscheinlich sowieso viel effizienter. – Roy

+0

Ich glaube, er bezog sich auf 'Array # count':' deals.count {| deal | deal.status == 'won'} '. –

0

, wenn Ihr Deal Objekte sind Active Objekte (die in der Regel ist die Fall für Modelle) können Sie die Zählung auf der Datenbank starten:

won = Deal.count_by_sql("select count(*) from deals where status = 'won'")

andere Art und Weise zu tun, wäre es die sQL-Abfrage zu schreiben, die alle die Zählung würde für Sie tun, und gruppieren sie nach Status:

count_by_status = Deal.find_by_sql("select status,count(*) from deals group by status;")

Dann können Sie das Ergebnis verwenden (die ein Array von Hashes sein wird, glaube ich).

1

können Sie Folgendes verwenden: -

Deal.find (: all,: Wählen Sie => 'Status, count (id) als deal_count': Gruppe => 'Status')

1

können Sie Verwenden Sie Array#select:

deals = Deal.all 
won = deals.select { |deal| deal.status == 'won' }.length 
# similar for pending and lost 
+0

Ja, genau das habe ich gesucht. Obwohl die Antwort von Mladen Jablanović flexibler ist, benötigt sie einen zusätzlichen DB-Aufruf, bei dem sie mehr I/O als diese Lösung ausführen muss. Solange Sie wissen, welche Deal-Status es gibt, ist das besser. –

Verwandte Themen