Existuje nějaký důvod (jiný než již zmíněný datum), proč byste nepoužili vestavěné možnosti skupinových funkcí v ActiveRecord? Zdá se, že vás znepokojuje „post-processing“, což si nemyslím, že by vás mělo znepokojovat.
Jste v Rails, takže byste pravděpodobně měli nejprve hledat řešení Rails[1]. Moje první myšlenka by byla udělat něco jako
Product.average(:sales_price, :group => "DATE(created_at)", :conditions => ["merchant_id=?", 1])
který ActiveRecord proměnil v podstatě na SQL, které jste popsal. Za předpokladu, že existuje deklarovaný has_many
spojení mezi obchodníkem a produktem, pak by bylo pravděpodobně lepší použít to, takže něco jako:
ave_prices = Merchant.find(1).products.average(:sales_price, :group => "DATE(created_at)")
(Doufám, že váš popis modelu jako "products_sold" je nějaký druh chyby v přepisu, mimochodem - pokud ne, jste poněkud mimo zprávu s názvem vaší třídy!)
Po tom všem jste zpátky tam, kde jste začali, ale dostali jste se tam konvenčnějším způsobem Rails (a Rails si opravdu cení konvencí!). Nyní musíme vyplnit mezery.
Předpokládám, že znáte své časové období, řekněme, že je definováno jako všechna data z from_date
do to_date
.
date_aves = (from_date..to_date).map{|dt| [dt, 0]}
Tím se vytvoří úplný seznam dat jako pole. Nepotřebujeme data, kde jsme dostali průměr:
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
To se mi zdá trochu nepřehledné:myslím, že by to mohlo být stručnější a čistší. Raději bych prozkoumal vytvoření hash nebo struktury než zůstávat v polích.
[1] Neříkám, že nepoužívejte SQL – nastávají situace, kdy ActiveRecord nedokáže vygenerovat nejúčinnější dotaz a vy se vrátíte k find_by_sql
. To je v pořádku, má to tak být, ale myslím, že byste to měli zkusit použít jen jako poslední možnost.