¿Hay alguna razón (aparte de la fecha ya mencionada) por la que no usaría las capacidades de función de grupo integradas en ActiveRecord? Parece que le preocupa el "procesamiento posterior", que no creo que sea realmente algo de lo que preocuparse.
Está en Rails, por lo que probablemente debería buscar primero una solución de Rails[1]. Mi primer pensamiento sería hacer algo como
Product.average(:sales_price, :group => "DATE(created_at)", :conditions => ["merchant_id=?", 1])
que ActiveRecord se convirtió prácticamente en el SQL que describiste. Asumiendo que hay un has_many
declarado asociación entre Comerciante y Producto, entonces probablemente sería mejor usar eso, así que algo como:
ave_prices = Merchant.find(1).products.average(:sales_price, :group => "DATE(created_at)")
(Espero que su descripción del modelo como "productos_vendidos" sea algún tipo de error de transcripción, por cierto; si no, ¡está un poco equivocado con el nombre de su clase!)
Después de todo eso, estás de regreso donde empezaste, pero llegaste allí de una manera más convencional de Rails (¡y Rails realmente valora las convenciones!). Ahora tenemos que llenar los espacios en blanco.
Asumiré que conoce su rango de fechas, digamos que está definido como todas las fechas desde from_date
hasta to_date
.
date_aves = (from_date..to_date).map{|dt| [dt, 0]}
Eso construye la lista completa de fechas como una matriz. No necesitamos las fechas en las que obtuvimos un promedio:
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
Ese lote me parece un poco desordenado:creo que podría ser más conciso y más limpio. Investigaría construir un Hash o Struct en lugar de permanecer en matrices.
[1] No estoy diciendo que no use SQL:ocurren situaciones en las que ActiveRecord no puede generar la consulta más eficiente y recurre a find_by_sql
. Eso está bien, se supone que debe ser así, pero creo que deberías tratar de usarlo solo como último recurso.