Existe uma razão (além da data já mencionada) pela qual você não usaria os recursos internos da função de grupo no ActiveRecord? Você parece estar preocupado com o "pós-processamento", o que eu não acho que seja realmente algo para se preocupar.
Você está no Rails, então provavelmente deveria procurar uma solução Rails primeiro[1]. Meu primeiro pensamento seria fazer algo como
Product.average(:sales_price, :group => "DATE(created_at)", :conditions => ["merchant_id=?", 1])
qual ActiveRecord se transformou em praticamente o SQL que você descreveu. Supondo que haja um
has_many
declarado associação entre o comerciante e o produto, provavelmente seria melhor usar isso, então algo como:ave_prices = Merchant.find(1).products.average(:sales_price, :group => "DATE(created_at)")
(Espero que sua descrição do modelo como "produtos_vendidos" seja algum tipo de erro de transcrição, aliás - se não, você está um pouco fora da mensagem com a nomenclatura da sua classe!)
Depois de tudo isso, você está de volta onde começou, mas chegou lá de uma maneira mais convencional do Rails (e o Rails realmente valoriza as convenções!). Agora precisamos preencher as lacunas.
Presumo que você conheça seu período, digamos que esteja definido como todas as datas de
from_date
para to_date
. date_aves = (from_date..to_date).map{|dt| [dt, 0]}
Isso cria a lista completa de datas como uma matriz. Não precisamos das datas em que obtivemos uma média:
ave_price_dates = ave_prices.collect{|ave_price| ave_price[0]} # build an array of dates
date_aves.delete_if { |dt| ave_price.dates.index(dt[0]) } # remove zero entries for dates retrieved from DB
date_aves.concat(ave_prices) # add the query results
date_aves.sort_by{|ave| ave[0] } # sort by date
Esse lote me parece um pouco confuso:acho que poderia ser mais sucinto e mais limpo. Eu investigaria a construção de um Hash ou Struct em vez de ficar em arrays.
[1] Não estou dizendo para não usar SQL - ocorrem situações em que o ActiveRecord não pode gerar a consulta mais eficiente e você recorre ao
find_by_sql
. Tudo bem, deveria ser assim, mas acho que você deve tentar usá-lo apenas como último recurso.