Como posso contar o número de registros que possuem um valor exclusivo em um determinado campo no ROR?
-
09-06-2019 - |
Pergunta
Tenho um conjunto de registros que inclui um campo de data e desejo determinar quantas datas exclusivas estão representadas no conjunto de registros.
Algo como:
Record.find(:all).date.unique.count
mas é claro que isso não parece funcionar.
Solução
O que você está procurando é o seguinte SQL:
SELECT COUNT(DISTINCT date) FROM records
ActiveRecord tem isso integrado:
Record.count('date', :distinct => true)
Outras dicas
Isso mudou ligeiramente nos trilhos 4 e superiores :distinct => true
agora está obsoleto.Usar:
Record.distinct.count('date')
Ou se você quiser a data e o número:
Record.group(:date).distinct.count(:date)
Fora do SQL:
Record.find(:all).group_by(&:date).count
ActiveSupport Enumerável#group_by é indispensável.
o mais recente #count
no código-fonte do Rails aceita apenas 1 parâmetro.ver: http://api.rubyonrails.org/classes/ActiveRecord/Calculations.html#method-i-count
então eu alcancei o requisito
Record.count('DISTINCT date')
Detalhando a resposta:
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}
Como mencionei aqui, no Rails 4, usando (...).uniq.count(:user_id)
como mencionado em outras respostas (para esta pergunta e em outras partes do SO), na verdade levará a um extra DISTINCT
estando na consulta:
SELECT DISTINCT COUNT(DISTINCT user_id) FROM ...
O que realmente precisamos fazer é usar nós mesmos uma string SQL:
(...).count("DISTINCT user_id")
O que nos dá:
SELECT COUNT(DISTINCT user_id) FROM ...
Além disso, certifique-se de ter um índice no campo em seu banco de dados, caso contrário a consulta ficará lenta rapidamente.
(É muito melhor fazer isso em SQL, caso contrário você coloca toda a tabela db na memória apenas para responder a contagem.)