Seu erro foi usar fill_at em ordem, provavelmente no escopo padrão.
Você pode corrigi-lo usando sem escopo para eliminar escopos padrão:
Income.unscoped
.group('date(filled_at)')
.having("date(filled_at) > ?", Date.today - n)
.sum(:lines_price)
ou
Income.unscoped
.group('date(filled_at)')
.having("date(filled_at) > ?", Date.today - n)
.sum(:lines_price)
.order('date(filled_at) ASC')
mas acho que melhor será usar where ao invés de ter
Income.unscoped
.where("date(filled_at) > TIMESTAMP ?", Date.today - n)
.group('date(filled_at)')
.sum(:lines_price)
.order('date(filled_at) ASC')
SQLFiddle
Você deve ter cuidado ao usar TIMESTAMP porque 2012-12-04 se tornará 2012-12-04 00:00:00, portanto, se você não quiser este dia no resultado, use Date.today - (n - 1)
Se você criar um índice na coluna preenchida_at
create index incomes_filled_at on incomes(filled_at);
migração:
add_index :incomes, :filled_at
e você tem um monte de dados nesta tabela índice será usado na filtragem. Portanto, a consulta deve ser muito mais rápida.
Então, basta escrever os dois e testar o que é mais rápido (você precisa criar o índice emfilled_at se não tiver um).