Finns det en anledning (annat än det datum ett redan nämnt) till varför du inte skulle använda de inbyggda gruppfunktionsfunktionerna i ActiveRecord? Du verkar vara bekymrad över "efterbearbetning", vilket jag inte tycker är något att oroa sig för.
Du är i Rails, så du bör förmodligen leta efter en Rails-lösning först[1]. Min första tanke skulle vara att göra något liknande
Product.average(:sales_price, :group => "DATE(created_at)", :conditions => ["merchant_id=?", 1])
som ActiveRecord förvandlade till i stort sett den SQL du beskrev. Förutsatt att det finns en deklarerad has_many
koppling mellan säljare och produkt, då skulle du förmodligen vara bättre att använda det, så något i stil med:
ave_prices = Merchant.find(1).products.average(:sales_price, :group => "DATE(created_at)")
(Jag hoppas att din beskrivning av modellen som "produkter_sålda" är något slags transkriptionsfel, btw - om inte, är du något ointressant med ditt klassnamn!)
Efter allt det är du tillbaka där du började, men du kom dit på ett mer konventionellt Rails-sätt (och Rails värdesätter verkligen konventioner!). Nu måste vi fylla i luckorna.
Jag antar att du känner till ditt datumintervall, låt oss säga att det definieras som alla datum från from_date
till to_date
.
date_aves = (from_date..to_date).map{|dt| [dt, 0]}
Det bygger den kompletta listan över datum som en array. Vi behöver inte datumen där vi fick ett genomsnitt:
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
Det där ser lite rörigt ut för mig:jag tror att det kan vara snyggare och renare. Jag skulle undersöka att bygga en Hash eller Struct istället för att stanna i arrayer.
[1] Jag säger inte att du inte använder SQL - situationer uppstår där ActiveRecord inte kan generera den mest effektiva frågan och du faller tillbaka på find_by_sql
. Det är bra, det ska vara så, men jag tycker att du ska försöka använda det bara som en sista utväg.