# SELECT list expression references column which is neither grouped nor aggregated > Once a query has a GROUP BY, every column has to be either grouped or inside an aggregate. The message names the column. GROUP BY ALL fixes it in one word, and there are four variants depending on which clause the column was in. Source: https://docs.querylab.io/bigquery-errors/neither-grouped-nor-aggregated/ Updated: 2026-10-25 ```text SELECT list expression references column order_id which is neither grouped nor aggregated at [1:93] ``` ## What BigQuery means A `GROUP BY` collapses many rows into one. For each column in the output, BigQuery has to know which of the many values to print, and there are only two ways to tell it: put the column in the `GROUP BY`, so every row in the group has the same value, or wrap it in an aggregate, so the many values become one. `order_id` was neither. One group holds several order ids and BigQuery will not pick one for you. The column name in the message is the one to fix. The position is where it appears in the select list. ## The smallest query that reproduces it ```sql WITH orders AS (SELECT 1 AS order_id, 'a' AS customer_id, 10 AS amount) SELECT customer_id, order_id, SUM(amount) FROM orders GROUP BY customer_id ``` ## The fix Decide what you actually want from that column. **One row per order id.** It belongs in the `GROUP BY`: ```sql SELECT customer_id, order_id, SUM(amount) FROM orders GROUP BY customer_id, order_id ``` **Any one of the values, you do not care which.** Say so: ```sql SELECT customer_id, ANY_VALUE(order_id), SUM(amount) FROM orders GROUP BY customer_id ``` **All of the values.** Collect them: ```sql SELECT customer_id, ARRAY_AGG(order_id), SUM(amount) FROM orders GROUP BY customer_id ``` **Everything that is not an aggregate, grouped.** `GROUP BY ALL` works out the list for you: ```sql SELECT customer_id, order_id, SUM(amount) FROM orders GROUP BY ALL ``` This is the right answer more often than people expect, and it stays correct when you add a column to the select list later. It is also the wrong answer when you meant to aggregate the column, because it will silently group by it instead and give you more rows than you wanted. **The whole row for the top order per customer.** This is the case `GROUP BY` is bad at. Use [`QUALIFY`](https://docs.querylab.io/bigquery/qualify/) with `ROW_NUMBER()` instead: ```sql SELECT * FROM orders QUALIFY ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY amount DESC) = 1 ``` ## The four variants The same rule applies in four places, and BigQuery names the clause: | Message | What you wrote | | ---------------------------------------------------------------------------------------- | ------------------------------------------------- | | `SELECT list expression references column X which is neither grouped nor aggregated` | a bare column in the select list | | `ORDER BY clause expression references column X which is neither grouped nor aggregated` | `ORDER BY` a column you did not group by | | `HAVING clause expression references column X which is neither grouped nor aggregated` | `HAVING` on a bare column instead of an aggregate | | `Star expansion expression references column X which is neither grouped nor aggregated` | `SELECT *` together with a `GROUP BY` | `SELECT * ... GROUP BY customer_id` reports the first ungrouped column it finds, which can be a column you were not thinking about. The `HAVING` one usually means you wrote `HAVING amount > 1` when you meant `HAVING SUM(amount) > 1`. An aggregate in `HAVING` is always allowed, even if it is not in the select list. ## Queries that look wrong but run **Grouping by a select alias.** BigQuery resolves the `GROUP BY` name against the select list first: ```sql SELECT a AS g, COUNT(*) FROM t GROUP BY g ``` **Grouping by position.** `GROUP BY 1` means the first select item: ```sql SELECT a, COUNT(*) FROM t GROUP BY 1 ``` ## Different errors that look like this one **A window function alongside a `GROUP BY`**, as long as its arguments are themselves grouped or aggregated. `SUM(a) OVER (PARTITION BY a)` in a query grouped by `b` fails with this error on `a`, because the window function sees the post-aggregation rows where `a` no longer exists as a single value. **An aggregate of an aggregate** is a different error, not this one: `Multi-level aggregation requires the enclosing aggregate function to have one or more GROUP BY modifiers.` ## In Querylab.io Querylab.io flags the select-list case in the browser as you type, with the column underlined and two quick fixes: add the column to `GROUP BY`, or replace the clause with `GROUP BY ALL`. See [Code quality](https://docs.querylab.io/writing-sql/code-quality/) and [GROUP BY](https://docs.querylab.io/bigquery/group-by/). ## Sources Based on the BigQuery documentation by Google, CC BY 4.0, rewritten with examples checked against BigQuery: - [Query syntax, GROUP BY clause](https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#group_by_clause) - [Aggregate function calls](https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate-function-calls)