I'm following along Bate's tut on graphs & charts but am getting an error.
This is the error I'm getting
PG::Error: ERROR: column "orders.created_at" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT created_at, sum(amount) as total_amount FROM "orders"...
^
: SELECT created_at, sum(amount) as total_amount FROM "orders" WHERE ("orders"."created_at" BETW
And this is the code I'm using in my Orders model
def self.total_grouped_by_day(start)
orders = where(created_at: start.beginning_of_day..Time.zone.now)#.all
orders = orders.group("date(created_at)")
orders = orders.select("date(created_at), sum(amount) as total_amount")
orders.group_by { |order| order.created_at.to_date }
end
and in my helper
def orders_chart_data
orders_by_day = Order.total_grouped_by_day(3.weeks.ago)
(3.weeks.ago.to_date..Date.today).map do |date|
{
created_at: date,
price: orders_by_day[date].first.try(:total_amount) || 0
}
end
end
I'm using Postgres (which I'm pretty sure is the main reason I'm getting this error) & Rails 3.x.x. Why is this error occurring & how do I fix it?
Thank you in advance
In my console:
Order.where(created_at: 3.weeks.ago.beginning_of_day..Time.zone.now).group("date(created_at)").select("date(created_at), sum(amount) as total_amount")
& this is what I get
[#<Order >, #<Order >, #<Order >]
weird..
running this in my console: Order.where(created_at: 3.weeks.ago.beginning_of_day..Time.zone.now).group("date(created_at)").select("date(created_at), sum(amount) as total_amount").first.total_amount
gives me this:
Creating scope :page. Overwriting existing method Order.page.
Order Load (18.1ms) SELECT date(created_at), sum(amount) as total_amount FROM "orders" WHERE ("orders"."created_at" BETWEEN '2013-07-05 00:00:00.000000' AND '2013-07-26 23:50:38.876609') GROUP BY date(created_at) LIMIT 1
=> "10.0"
You are grouping on date(created_at)
but not selecting that column. Change this line:
orders = orders.select("created_at, sum(amount) as total_amount")
to this:
orders = orders.select("date(created_at), sum(amount) as total_amount")
That will also result in a change to the next line's group_by as well.
From one of my projects, using slightly different attributes, but doing the same thing as you:
1.9.3p327 > User.group('date(created_at)').select('date(created_at), sum(id) as total_amount').first.attributes
User Load (1.2ms) SELECT date(created_at), sum(id) as total_amount FROM "users" GROUP BY date(created_at) LIMIT 1
=> {"date"=>"2011-09-27", "total_amount"=>"657"}
A cast to date would be simplest & fastest. Here the raw SQL since I am no expert with Ruby syntax (and no fan of ORMs butchering SQL in general).
SELECT created_at::date, sum(amount) AS total_amount
FROM orders
WHERE created_at ...
GROUP BY created_at::date
ORDER BY created_at::date
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With