Skip to content
Oracle Database

Oracle Error ORA-00979

must appear in the GROUP BY clause or be used in an aggregate function (not a GROUP BY expression)

Applies to: Oracle Database 19c, 21c, 23ai and 26ai (wording differs: see below)
Last technically reviewed 24 October 2026 on Oracle Database Error Messages reference (26ai, 21c and 19c); not run locally
The full message
ORA-00979: STATUS: must appear in the GROUP BY clause or be used in an aggregate function
Other forms of this message
Oracle Database 19c and 21c (no expression named)
ORA-00979: not a GROUP BY expression
SQL*Plus and SQLcl show the failing line first
ERROR at line 1:
ORA-00979: STATUS: must appear in the GROUP BY clause or be used in an aggregate function
Error code
ORA-00979
Product
Oracle Database
Versions
Oracle Database 19c, 21c, 23ai and 26ai (wording differs: see below)
Last reviewed
24 October 2026

What it means

ORA-00979 means the query has a GROUP BY clause, but the SELECT list, HAVING clause or ORDER BY clause uses an expression that is neither in the GROUP BY nor inside an aggregate function.

After GROUP BY, each group becomes one row, so only the grouped expressions, aggregates over the group and constants still have a single value. Oracle's current reference explains that the SELECT, HAVING and ORDER BY clauses are processed after GROUP BY: an expression that is not part of the grouped result can no longer be referenced there. The current message names the expression; 19c and 21c print only "not a GROUP BY expression", so you have to find it yourself.

The match is on the expression, not just the column: the 19c reference says the expression must match one of the expressions in the GROUP BY clause. Grouping by TRUNC(order_date) and selecting order_date fails, for example. If the query has no GROUP BY clause at all, Oracle raises ORA-00937 instead.

Common causes

  • A column was added to the SELECT list of a grouped query but not to the GROUP BY clause.
  • ORDER BY or HAVING uses a column that is not grouped, such as ORDER BY order_date in a query grouped by customer_id.
  • The GROUP BY uses an expression (TRUNC(order_date), UPPER(name), EXTRACT(YEAR FROM ...)) but the SELECT list uses the bare column or a different expression.
  • A query joins a lookup table and selects its descriptive column (for example c.name) while grouping only by the key c.customer_id.
  • A scalar subquery in the SELECT list of a grouped query refers to a column of the outer query that is not grouped.

Diagnose it

Read-only These queries only read the data dictionary (USER_, ALL_ and DBA_ views) and dynamic performance views (V$). They do not change data, privileges or settings, so they are safe to run first. DBA_ and V$ views need the matching privileges.

Read the expression from the message (current releases)

In current releases the text before the colon is the expression that is missing from GROUP BY. In 19c and 21c, compare every non-aggregated expression in SELECT, HAVING and ORDER BY with the GROUP BY list, character for character. SQL*Plus marks the first one it rejects with an asterisk.

Check whether the extra column is really one value per group

If you believe the ungrouped column has only one value in each group (a customer name per customer id, say), prove it before you add it to GROUP BY.

SELECT o.customer_id, COUNT(DISTINCT c.name) AS names_per_group
FROM shop.orders o
JOIN shop.customers c ON c.customer_id = o.customer_id
GROUP BY o.customer_id
HAVING COUNT(DISTINCT c.name) > 1;
What to look for

No rows: the column is functionally one value per group, and adding it to GROUP BY does not change the result. Any rows returned mean the groups would split, so decide which value you want (MIN, MAX, LISTAGG) instead.

How to fix it

Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.

Add the expression to GROUP BY

Read-only

When the column should define the groups, or is one value per group, list it in GROUP BY exactly as it is written in the SELECT list.

SELECT o.customer_id, c.name, COUNT(*) AS order_count
FROM shop.orders o
JOIN shop.customers c ON c.customer_id = o.customer_id
GROUP BY o.customer_id, c.name;

Wrap it in an aggregate to choose one value per group

Read-only

When a group has many values and you want one of them, say which: the latest date, the first status alphabetically, or all of them joined as a list.

SELECT customer_id,
       COUNT(*)        AS order_count,
       MAX(order_date) AS last_order,
       LISTAGG(status, ', ') WITHIN GROUP (ORDER BY status) AS statuses
FROM shop.orders
GROUP BY customer_id;

Use the same expression in SELECT, HAVING and ORDER BY as in GROUP BY

Read-only

When you group by a calculated value, repeat that calculation wherever you use it (or group in a subquery and give it an alias there).

SELECT TRUNC(order_date, 'MM') AS order_month, COUNT(*) AS order_count
FROM shop.orders
GROUP BY TRUNC(order_date, 'MM')
ORDER BY TRUNC(order_date, 'MM');

Order by an aggregate or a grouped column only

Read-only

ORDER BY is processed after GROUP BY, so sort by something the grouped rows still have, such as the count or the latest date.

SELECT customer_id, COUNT(*) AS order_count
FROM shop.orders
GROUP BY customer_id
ORDER BY MAX(order_date) DESC;

Examples

Selecting a column that is not grouped

Not reproduced here: no Oracle Database is installed for this site. The result follows the message format in Oracle's current error reference with this example's column filled in; how the expression is printed (case, quoting, table alias) is illustrative. Oracle Database 19c and 21c print "ORA-00979: not a GROUP BY expression".

SELECT customer_id, status, COUNT(*) AS order_count
FROM orders
GROUP BY customer_id;
Expected result (documented format, not run)
ORA-00979: STATUS: must appear in the GROUP BY clause or be used in an aggregate function

Grouping by a truncated date but selecting the raw date

Not reproduced here: no Oracle Database is installed for this site. The message format comes from Oracle's current error reference; the printed expression is illustrative, and 19c and 21c show "not a GROUP BY expression". Selecting TRUNC(order_date) instead matches the GROUP BY expression.

SELECT order_date, COUNT(*) AS order_count
FROM orders
GROUP BY TRUNC(order_date);
Expected result (documented format, not run)
ORA-00979: ORDER_DATE: must appear in the GROUP BY clause or be used in an aggregate function

ORDER BY a column that the groups no longer have

Not reproduced here: no Oracle Database is installed for this site. The message format comes from Oracle's current error reference, which lists ORDER BY among the clauses processed after GROUP BY; the printed expression is illustrative. Use ORDER BY MAX(order_date) or another aggregate.

SELECT customer_id, COUNT(*) AS order_count
FROM orders
GROUP BY customer_id
ORDER BY order_date;
Expected result (documented format, not run)
ORA-00979: ORDER_DATE: must appear in the GROUP BY clause or be used in an aggregate function

How to prevent it

Before running a grouped query, check each non-aggregated expression in SELECT, HAVING and ORDER BY against the GROUP BY list, written the same way. When the grouping key is a calculation, group in a subquery or a WITH clause, give it an alias there, and use the alias in the outer query.

Group by the key and pick descriptive columns deliberately: either group by them too (after checking they are one value per key) or wrap them in MIN, MAX or LISTAGG. See ORDER BY, GROUP BY and HAVING explained.

Common questions

How do I fix ORA-00979 not a GROUP BY expression?

Find the expression in SELECT, HAVING or ORDER BY that is not grouped (current releases name it in the message), then either add it to GROUP BY exactly as written or wrap it in an aggregate such as MAX, MIN or LISTAGG.

Why does it fail when I group by TRUNC(order_date) and select order_date?

Oracle compares expressions, not just column names. order_date has many values inside one TRUNC(order_date) group, so it is not part of the grouped result. Select TRUNC(order_date) as well, or wrap order_date in MIN or MAX.

How is ORA-00979 different from ORA-00937?

ORA-00979 needs a GROUP BY clause that is missing one of the expressions you use. ORA-00937 is raised when there is no GROUP BY at all and a plain column sits next to a group function.

Learn more on CodeWithSQL

Official documentation

Last technically reviewed 24 October 2026; examples and diagnostics run on Oracle Database Error Messages reference (26ai, 21c and 19c); not run locally. Messages and explanations follow Oracle's Database Error Messages reference; no Oracle Database was available, so the examples were not run locally.

Still stuck on an Oracle error?

Browse the full Oracle error library, or get hands-on help from an experienced SQL professional.