GroupingError: ERROR: column must appear in the GROUP BY clause or be used in an aggregate function
You are not allowed to select reviews.id
(selected implicitly through the wildcard *
) without adding it to the GROUP BY
clause or applying an aggregate function like avg()
. The solution is to do one of the following:
- Remove the wildcard
*
from your select - Add the field
reviews.id
to your group clause - Select
reviews.id
explicitly and apply an aggregate function to it (e.g.sum(reviews.id)
) - Replace the wildcard
*
with the table-specific wildcardalbums.*
The second and third option do not make much sense in your scenario though.
Based on your comment, I added option four.
Rails PG GroupingError column must appear in the GROUP BY clause
I don't know why you want to select likes.id
in the first place. I see that you basically want the like_count
for each Idea; I don't see the point in selecting likes.id
. Also, when you already have the ideas.id
, I don't see why you would want to get the value of likes.likeable_id
since they'll both be equal. :/
Anyway, the problem is since you're grouping by likeable_id
(basically ideas.id
), you can't "select" likes.id
since they would be "lost" by the grouping.
I suppose SQLite is lax about this. I imagine it wouldn't group things properly.
ANYWAY(2) =>
Let me propose a cleaner solution.
# model
class Idea < ActiveRecord::Base
# to save you the effort of specifying the join-conditions
has_many :likes, foreign_key: :likeable_id
end
# in your code elsewhere
ideas = \
Idea.
joins(:likes).
group("ideas.id").
select("COUNT(likes.id) AS like_count, ideas.id, ideas.title, ideas.intro").
order("like_count DESC")
If you still want to get the IDs of likes for each item, then after the above, here's what you could do:
grouped_like_ids = \
Like.
select(:id, :likeable_id).
each_with_object({}) do |like, hash|
(hash[like.likeable_id] ||= []) << like.id
end
ideas.each do |idea|
# selected previously:
idea.like_count
idea.id
idea.title
idea.intro
# from the hash
like_ids = grouped_like_ids[idea.id] || []
end
Other readers: I'd be very interested in a "clean" one-query non-sub-query solution. Let me know in the comments if you leave a response. Thanks.
PostgreSQL -must appear in the GROUP BY clause or be used in an aggregate function
@myestate1 = Estate.where(:Mgmt => current_user.Company)
@myestate = @myestate1.select("DISTINCT(user_id)")
this is what I did.
column likes.id must appear in the GROUP BY clause or be used in an aggregate function
What the error is telling you, is that you're selecting for "likes.id", but there is no single likes.id that the database can give you.
This is because by default when you don't tell Rails what you need, Rails will select EVERYTHING.
Think, do you actually need "likes.id"? Looks to me that you're grouping by exercise_id so what you're trying to get is exercises and their like counts. (correct me if I'm wrong.) You don't actually need specific like id-s.
If that's so, we need to tell rails about our intention.
Like.group(:exercise_id).order('COUNT(exercise_id) DESC').select(:exercise_id)
If you also need the count itself, just add it to the select.
Something else you might want to try is just .count
. It's pretty smart and will respect your grouping. See if this helps.
Like.group(:exercise_id).count
Rails: must appear in the GROUP BY clause or be used in an aggregate function
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"}
Postgres: column must appear in the GROUP BY clause or be used in an aggregate function
As the error implies, you need to add the GROUP BY clause after FROM:
So the query should look like:
select
'2019-09-11' as snapshot_date,
SUM(case when snapshot_date = '2019-09-11' then balance end) as opening_balance,
SUM(case when snapshot_date = '2019-09-09' then balance end) as closing_balance,
year
from snapshot
group by year
See: https://www.javatpoint.com/postgresql-group-by-clause
Postgresql Column must appear in the GROUP BY clause or be used in an aggregate function when using CASE expression inside ORDER BY clause
Your problem has a couple of roots:
Most importantly, don't use the same name for an output column that is distinct from an input column (of the same name). That's a loaded foot-gun.
Secondly, make it a habit to table-qualify all columns used in a complex query involving multiple tables. Even if that seems to work, it might already be doing something else than you think. And even if it works correctly it may break later, if any column names are changed (added, removed renamed). With some bad luck it breaks silently, and your query happily ever after produces nonsense.
Thirdly, the SQL standard, which has somewhat confusing visibility rules. See:
- GROUP BY + CASE statement
In your working alternative query, "value"
resolves to the output column "value"
, which hides any input column of the same name in ORDER BY
. That works as expected (that is, if you actually meant to target the output column).
In your failing query, "value"
resolves to the input column "measurementResults.value"
. You cannot throw output columns into a new computation in ORDER BY
, you can only use them "as is". So, with output columns out of the way, "value"
resolves to the input column (now not hidden any more). And that leads to the reported error. Obviously, you cannot order by an input column after aggregating - except if you grouped by it, directly or indirectly.
You could repair your query with:
ORDER BY (ranking = 'greater') IS TRUE, "value" DESC
The sorts all rows where ranking = 'greater'
is not true to the top - like your CASE
expression would. So treating null
and false
alike.
Subtle difference: Those leading rows are sorted by value
, while your original would list them in arbitrary order. May or may not be welcome.
- Sorting null values after all others, except special
- Best way to check for "empty or null value"
I assume you are aware that null
values sort on top in descending order? And that you can change that? See:
- Sort by column ASC, but NULL values first?
If that's not good enough (or for more complex expressions), you must be more verbose and explicit: one way is to wrap the whole query into a subquery, and order (and limit!) in the outer SELECT
:
SELECT avg_value, min_timestamp, min_ranking
FROM (
SELECT ir.ranking -- !
, avg(mr."value") AS avg_value -- !
, min(m."timestamp") AS min_timestamp -- !
, min(ir.ranking) AS min_ranking -- !
FROM measurement m
JOIN "measurementResults" mr ON mr.measurement = m.id
JOIN conditions c ON c.measurement = m.id
JOIN "testProtocolItemResults" ir ON ir.id = mr."testProtocolItemResults"
JOIN "testProtocolSessionItem" si ON si.id = m."testProtocolSessionItem"
WHERE m."athlete" = 334
AND mr."testProtocolItemResults" = 1
AND c."conditions" = '6'
GROUP BY si."testProtocolSession", ir.ranking
) sub
ORDER BY CASE WHEN ranking = 'greater' THEN "value" END DESC
LIMIT 3
Especially for queries with a small LIMIT
, this may be more expensive if Postgres cannot optimize the query plan as well any more.
Aside:
Use legal, loser-case identifiers, so you don't have to double-quote.
And use table aliases to de-noise your big queries.
Rails / Postgres: “must appear in the GROUP BY clause or be used in an aggregate function”
Your mistake was to use filled_at in order by probably in default scope.
You can fix it using unscoped to eliminate default scopes:
Income.unscoped
.group('date(filled_at)')
.having("date(filled_at) > ?", Date.today - n)
.sum(:lines_price)
or
Income.unscoped
.group('date(filled_at)')
.having("date(filled_at) > ?", Date.today - n)
.sum(:lines_price)
.order('date(filled_at) ASC')
but I think that better will be to use where instead of having
Income.unscoped
.where("date(filled_at) > TIMESTAMP ?", Date.today - n)
.group('date(filled_at)')
.sum(:lines_price)
.order('date(filled_at) ASC')
SQLFiddle
You have to be careful about using TIMESTAMP because 2012-12-04 will become 2012-12-04 00:00:00 so if you don't want this day in result use Date.today - (n - 1)
If you create index on filled_at column
create index incomes_filled_at on incomes(filled_at);
migration:
add_index :incomes, :filled_at
and you have a lot of data in this table index will be used in filtering. So query should be much faster.
So just write both and test which is faster (you have to create index on filled_at if you don't have one).
PG::GroupingError: ERROR: column events.id must appear in the GROUP BY clause or be used in an aggregate function
Event
.order(:popularity)
.joins(:keywords)
.group('events.id') # <======
.where(keywords: { category: 'taxonomy' })
.group('keywords.name')
Related Topics
Invoking a Large Set of SQL from a Rails 4 Application
How to Compare Software Versions Using SQL Server
Concat Function Is Not Working - Invalid Number of Arguments
What Is the Internal Representation of Datetime in SQL Server
Query JSON Dictionary Data in SQL
Job Queue as SQL Table with Multiple Consumers (Postgresql)
How to Delete Rows in Tables That Contain Foreign Keys to Other Tables
Applying the Min Aggregate Function to a Bit Field
Moving Average Based on Timestamps in Postgresql
Rails 3 Activerecord Query Using Both SQL in and SQL or Operators
How Does Select Top Works When No Order by Is Specified
Is Natural (Join) Considered Harmful in Production Environment
Oracle Get Checksum Value for a Data Chunk Defined by a Select Clause
Access a Column Aliases in the Where Clause in Postgresql
In SQL Server, When Should You Use Go and When Should You Use Semi-Colon ;