2009-07-07 5 views
0

Existe-t-il un moyen d'utiliser les calculs ActiveRecord tout en acquérant des noms de champs pertinents? Par exemple, j'aimerais trouver l'âge moyen de toutes les personnes ayant les différents noms de famille. Fondamentalement, je voudrais utiliser:(Rails, ActiveRecord) Comment utiliser les calculs ActiveRecord tout en récupérant les noms de champs?

Person.average(:age, :group_by => "last_name") 

... comme un substitut à

"Select last_name, AVG(age) FROM People GROUP BY last_name" 

Toutes les idées?

+0

Que voulez-vous dire par "Acquisition de noms de champs pertinents"? – Ethan

+0

Champs arbitraires de mon choix. –

Répondre

1

Cela fonctionne à peu près exactement comme vous l'avez décrit (bien que je pense que vous utiliseriez: group au lieu de: group_by) pour les champs uniques. Le retour est un OrderedHash, donc les clés seront les noms et les valeurs seront l'âge moyen pour ce nom.

Étant donné que tout champ que vous renvoyez doit être inclus dans le groupe, si vous souhaitez ajouter des champs supplémentaires, vous pouvez essayer de faire quelque chose d'un peu hackish. Dans Postgres, par exemple, vous pouvez concaténer les champs supplémentaires comme ceci:

Person.average(:age, :group => "first_name || ',' || last_name") 

Les clés du retour serait la séparées par des virgules noms et prénoms. Si vous souhaitez récupérer les objets ActiveRecord :: Base, vous devez recourir aux requêtes de style "SELECT ...".

0
Person.average(:age, :select => "last_name", :group => "last_name") 

Il renvoie un hachage où la clé est la valeur for_last name, la valeur est le résultat du calcul de la moyenne.

+0

Si vous spécifiez une valeur: select dans les options, il utilise celle-ci à la place de la colonne pour le groupe afin que vous obteniez une requête comme: SELECT avg (last_name) FROM people GROUP BY last_name – Shadwell

+0

Etes-vous sûr? Je l'ai essayé et il a lancé la requête suivante "SELECT AVG (last_name) comme avg_last_name, last_name comme last_name ..." –

+0

Ouais, c'est exactement ce que j'ai eu. L'exigence est que la colonne moyennée soit l'âge et non le nom de famille. C'est un peu bizarre - il y a une ligne de code qui utilise simplement la valeur de l'option: select au lieu du paramètre column_name si: select est présent. – Shadwell

1

Pour retourner un attribut sur la classe que vous établissez la moyenne, il vaut probablement mieux utiliser la méthode standard find(:all, ...) avec une option personnalisée :select.

Ainsi, votre exemple serait:

groups_of_people = Person.find(:all, 
    :select => 'avg(age) as avg_age, last_name', 
    :group => 'last_name') 

Ils ne sont pas vraiment des cas personne alors (bien qu'ils soient de retour en tant que tel), mais vous pouvez le faire:

groups_of_people.each do |g| 
    g.last_name 
    g.avg_age 
end 
Questions connexes