2008-08-31 10 views

Répondre

79

Qu'est-ce que vous allez pour est l'instruction SQL suivante:

SELECT COUNT(DISTINCT date) FROM records 

ActiveRecord a ce construit:

Record.count('date', :distinct => true) 
+1

Est-il possible de le faire en utilisant plusieurs colonnes comme un champ d'application? –

+13

Ceci est maintenant obsolète (rails 4), voir la réponse ci-dessous. – Yule

16

En dehors de SQL:

Record.find(:all).group_by(&:date).count 

Enumerable#group_by de ActiveSupport est indispensable .

2

De même, assurez-vous d'avoir un index sur le champ dans votre base de données, sinon cette requête deviendra rapidement sloooow.

(Il est préférable de le faire dans SQL, sinon vous tirez toute la table db en mémoire juste pour répondre au nombre.)

+1

La réponse de nex3 générera correctement l'instruction SQL 'COUNT'. http://guides.rubyonrails.org/active_record_querying.html#calculations – Kevin

+1

Bonne astuce sur l'index, cependant. – Kevin

82

Cela a légèrement changé dans des rails 4 et au-dessus :distinct => true est maintenant dépréciée. Utilisation:

Record.distinct.count('date') 

Ou si vous voulez que la date et le numéro:

Record.group(:date).distinct.count(:date) 
+4

Ça ne marche pas pour moi. Utilisez '.count ('DISTINCT date')' – collimarco

+3

J'ai fini par utiliser 'Record.group (: date) .count.count'. – jayp

8

Détailler la réponse:

Post.create(:user_id => 1, :created_on => '2010-09-29') 
Post.create(:user_id => 1, :created_on => '2010-09-29') 
Post.create(:user_id => 2, :created_on => '2010-09-29') 
Post.create(:user_id => null, :created_on => '2010-09-29') 

Post.group(:created_on).count 
# => {'2010-09-29' => 4} 

Post.group(:created_on).count(:user_id) 
# => {'2010-09-29' => 3} 

Post.group(:created_on).count(:user_id, :distinct => true) # Rails <= 3 
Post.group(:created_on).distinct.count(:user_id) # Rails = 4 
# => {'2010-09-29' => 2} 
9

Comme je l'ai mentionné here, dans Rails 4, en utilisant (...).uniq.count(:user_id) comme mentionné dans d'autres réponses (pour cette question et ailleurs sur SO) conduira effectivement à un DISTINCT supplémentaire dans la requête:

SELECT DISTINCT COUNT(DISTINCT user_id) FROM ...

Ce que nous avons en fait à faire est d'utiliser une chaîne SQL nous:

(...).count("DISTINCT user_id")

Ce qui nous donne:

SELECT COUNT(DISTINCT user_id) FROM ...