ERROR 1111 (HY000): Invalid use of group function is raised when an aggregate function such as SUM(), COUNT(), AVG(), MAX(), or MIN() appears in a context where MySQL does not allow it — most commonly inside a WHERE clause or nested directly inside another aggregate call. The error symbol is ER_INVALID_GROUP_FUNC_USE.
Impact
The query is rejected immediately and no rows are returned. This is a parse-time / resolution-time error, so it fails before any data is read. Applications that dynamically build SQL — ORMs, report builders, analytics dashboards — are common sources of this error, typically surfacing as an unhandled database exception (e.g., PDOException, SQLException, ActiveRecord::StatementInvalid, or django.db.utils.OperationalError).
The error is deterministic: it will always fail until the SQL is corrected. No amount of retrying or adjusting data will change the outcome.
Common Causes
Aggregate function in a
WHEREclause.WHEREis evaluated before grouping, so aggregate results are not yet available. UsingSUM(amount) > 1000in aWHEREclause triggers this error.Nested aggregate functions. MySQL does not support
MAX(COUNT(*))orSUM(AVG(value))syntax. Each aggregate function must operate directly on a column or expression, not on the result of another aggregate.Aggregate in an
ONorJOINcondition. Placing an aggregate inside aJOIN ... ONclause is subject to the same restriction asWHERE— the condition is resolved before grouping.Aggregate in a
GROUP BYexpression. Referencing an aggregate in theGROUP BYlist itself (e.g.,GROUP BY COUNT(id)) is not valid MySQL syntax.ORM or query-builder generating invalid SQL. Some ORM filter methods map directly to
WHERE, and passing an aggregate expression through a.where()or.filter()call produces this error.
Troubleshooting and Resolution Steps
Replace
WHEREwithHAVINGfor aggregate conditions.HAVINGis evaluated after grouping and is the correct clause for filtering on aggregate results.-- Wrong: aggregate in WHERE SELECT customer_id, SUM(amount) AS total FROM orders WHERE SUM(amount) > 1000 GROUP BY customer_id; -- ERROR 1111 (HY000): Invalid use of group function -- Correct: use HAVING SELECT customer_id, SUM(amount) AS total FROM orders GROUP BY customer_id HAVING SUM(amount) > 1000;Rewrite nested aggregates using a subquery or CTE.
To find the maximum value of an aggregate (e.g., "which customer placed the most orders"), compute the inner aggregate in a subquery first.
-- Wrong: nested aggregate SELECT MAX(COUNT(*)) FROM orders GROUP BY customer_id; -- ERROR 1111 (HY000): Invalid use of group function -- Correct: subquery approach SELECT MAX(order_count) FROM ( SELECT customer_id, COUNT(*) AS order_count FROM orders GROUP BY customer_id ) AS counts; -- Correct: CTE approach (MySQL 8.0+) WITH counts AS ( SELECT customer_id, COUNT(*) AS order_count FROM orders GROUP BY customer_id ) SELECT MAX(order_count) FROM counts;Fix aggregate conditions in
JOINclauses using a derived table.If you need to join on an aggregated result, pre-aggregate in a subquery and then join to it.
-- Wrong: aggregate in JOIN condition SELECT c.name, o.total FROM customers c JOIN orders o ON o.customer_id = c.id AND SUM(o.amount) > 500; -- ERROR 1111 (HY000): Invalid use of group function -- Correct: pre-aggregate, then join SELECT c.name, t.total FROM customers c JOIN ( SELECT customer_id, SUM(amount) AS total FROM orders GROUP BY customer_id HAVING SUM(amount) > 500 ) AS t ON t.customer_id = c.id;Check ORM-generated SQL. Enable query logging to inspect the raw SQL your ORM produces:
SET GLOBAL general_log = 'ON'; SET GLOBAL general_log_file = '/tmp/mysql-general.log';Or use
EXPLAINto surface the query being sent. In many frameworks you can also enable SQL echo mode (e.g.,SQLALCHEMY_ECHO=truein Python,ActiveRecord::Base.loggerin Rails).
Additional Information
- The SQLSTATE code is
HY000(general error), which is a broad class — check the error number (1111) to distinguish it from otherHY000errors. - MySQL's
ONLY_FULL_GROUP_BYSQL mode (enabled by default since MySQL 5.7.5) enforces additional grouping rules, but error 1111 is a separate and stricter constraint that is always enforced regardless of SQL mode settings. - PostgreSQL raises a similar error with a clearer message: "aggregate functions are not allowed in WHERE". The fix is identical — use
HAVING. - MariaDB shares the same error code and behavior as MySQL for this constraint.
- Window functions (
ROW_NUMBER(),RANK(),LAG(), etc.) introduced in MySQL 8.0 are a different category from aggregate functions and follow their own placement rules — they belong in theSELECTlist orORDER BY, not inWHEREorHAVINGdirectly.
Frequently Asked Questions
Why can't I use SUM() in a WHERE clause?
WHERE filters rows before they are grouped. At the point MySQL evaluates WHERE, it is processing individual rows one at a time, so there is no group to aggregate over yet. The HAVING clause exists specifically for post-aggregation filtering and is the correct place for any condition that references an aggregate function.
What is the difference between WHERE and HAVING?
WHERE filters individual rows before grouping; HAVING filters groups after aggregation. You can use both in the same query: WHERE narrows down the raw rows first (and can use indexes efficiently), then HAVING filters the resulting groups. Putting non-aggregate conditions in WHERE rather than HAVING is also better for performance.
Can I use COUNT(*) inside MAX() in MySQL?
No. MySQL does not support nesting one aggregate directly inside another. Compute the inner aggregate in a subquery or CTE and apply the outer aggregate to that result set.
My ORM's .where() is generating this error — what should I do?
Most ORMs provide a separate method for HAVING clauses (e.g., .having() in ActiveRecord, SQLAlchemy, Laravel Eloquent, and Django's QuerySet.values().annotate().filter()). Switch to the appropriate HAVING method, or use a raw SQL fragment for complex cases.