Skip to content
Microsoft SQL Server

SQL Server Error 8120

Column is invalid in the select list because it is not in an aggregate or GROUP BY

Applies to: All supported SQL Server versions (2016 to 2025), Azure SQL Database, Azure SQL Managed Instance
Last technically reviewed 23 October 2026 on SQL Server 2025 (17.0.1145.4)
The full message
Msg 8120, Level 16, State 1, Line 1
Column 'dbo.Orders.order_date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Error number
8120
Severity
16 (user-correctable error)
State
1
Product
Microsoft SQL Server Database Engine
Versions
All supported SQL Server versions (2016 to 2025), Azure SQL Database, Azure SQL Managed Instance
Last reviewed
23 October 2026

What it means

Error 8120 means a grouped query (GROUP BY, or an aggregate such as COUNT or SUM) selects a column that is neither grouped nor aggregated, so SQL Server has no single value to return for it.

Once a query groups rows, each output row stands for a whole group. Every column in the SELECT list must then be either one of the GROUP BY expressions (one value per group) or wrapped in an aggregate such as SUM, MAX or COUNT (one value computed from the group). A bare column that varies inside the group has many possible values, so SQL Server rejects the query at compile time with 8120 at severity 16. It does not pick a value for you, unlike some MySQL configurations.

The message names the column as schema.table.column, using the real table name even if you wrote an alias, for example dbo.Customers.name for c.name. An aggregate with no GROUP BY at all, such as SELECT customer_id, COUNT(*) FROM dbo.Orders, counts as grouping the whole table and raises the same error. When the offending column is in ORDER BY instead of SELECT, the engine raises the related error 8127.

Common causes

  • A detail column (order date, product name, id) added to the SELECT list of a summary query without grouping or aggregating it.
  • Grouping by a key column such as c.id but selecting a descriptive column such as c.name that is not in GROUP BY.
  • An aggregate (COUNT, SUM, MAX) mixed with plain columns in a query that has no GROUP BY.
  • A query ported from MySQL, where a permissive sql_mode returned an arbitrary value for non-grouped columns.
  • Trying to fetch "the row with the latest date" using MAX() alone, when the other columns need a window function or a join.

Diagnose it

Read-only These queries only read metadata and dynamic management views. They do not change data, permissions or configuration, so they are safe to run first.

Compile the corrected grouped query without running it

sp_describe_first_result_set checks that every selected column is grouped or aggregated, and returns the output columns without executing the query.

EXEC sp_describe_first_result_set
     N'SELECT customer_id, MAX(order_date) AS last_order, SUM(total) AS spent
       FROM dbo.Orders
       GROUP BY customer_id;';
What to look for

One row per output column when the query is valid; error 8120 names any column that is still neither grouped nor aggregated.

Check whether a column is constant within each group

If you believe a column has only one value per group (for example a name per customer id), confirm it before adding it to GROUP BY or wrapping it in MAX.

SELECT c.id, COUNT(DISTINCT c.name) AS distinct_names
FROM dbo.Customers AS c
GROUP BY c.id
HAVING COUNT(DISTINCT c.name) > 1;
What to look for

No rows means the column is constant per group, so grouping by it as well gives the result you expect.

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 column to GROUP BY

Read-only

If the column describes the group (a customer name next to the customer id), group by it too. The number of groups does not change when the column is constant per key.

SELECT c.id, c.name, COUNT(*) AS order_count
FROM dbo.Customers AS c
JOIN dbo.Orders AS o ON o.customer_id = c.id
GROUP BY c.id, c.name;

Aggregate the column

Read-only

If you need one value from many, say which one: the latest date, the total, the count.

SELECT customer_id, MAX(order_date) AS last_order, SUM(total) AS total_spent
FROM dbo.Orders
GROUP BY customer_id;

Use a window function to keep row detail

Read-only

When you want each row plus a group total, or the full latest row per group, a window function avoids GROUP BY altogether.

SELECT id, customer_id, order_date, total
FROM (
    SELECT id, customer_id, order_date, total,
           ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date DESC) AS rn
    FROM dbo.Orders
) AS x
WHERE rn = 1;

Examples

A detail column in a summary query

CREATE TABLE dbo.Orders (id INT PRIMARY KEY, customer_id INT, order_date DATE, total DECIMAL(10,2));

SELECT customer_id, order_date, MAX(order_date) AS last_order
FROM dbo.Orders
GROUP BY customer_id;  -- order_date is neither grouped nor aggregated
Result
Msg 8120, Level 16, State 1, Line 3
Column 'dbo.Orders.order_date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.

Grouped by the key, selecting the name (the message shows the table, not the alias)

CREATE TABLE dbo.Customers (id INT PRIMARY KEY, name NVARCHAR(100));
CREATE TABLE dbo.Orders (id INT PRIMARY KEY, customer_id INT, total DECIMAL(10,2));

SELECT c.name, COUNT(*) AS order_count
FROM dbo.Customers AS c
JOIN dbo.Orders AS o ON o.customer_id = c.id
GROUP BY c.id;
Result
Msg 8120, Level 16, State 1, Line 4
Column 'dbo.Customers.name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.

An aggregate with no GROUP BY

CREATE TABLE dbo.Orders (id INT PRIMARY KEY, customer_id INT, total DECIMAL(10,2));

SELECT customer_id, COUNT(*) AS orders
FROM dbo.Orders;  -- GROUP BY customer_id is missing
Result
Msg 8120, Level 16, State 1, Line 3
Column 'dbo.Orders.customer_id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.

How to prevent it

Write grouped queries from the GROUP BY outwards: decide what one output row represents, list those columns in GROUP BY, and then make every other selected column an aggregate. If you find yourself wanting "the other columns of that row", reach for a window function such as ROW_NUMBER instead.

For a refresher on how grouping, HAVING and ORDER BY fit together, see ORDER BY, GROUP BY and HAVING explained and the aggregate functions guide.

Common questions

Why does the same query work in MySQL?

With ONLY_FULL_GROUP_BY disabled, MySQL returns a value from an arbitrary row of the group. SQL Server always enforces the rule, so you must group or aggregate the column explicitly.

Can I GROUP BY a column alias from the SELECT list?

No. GROUP BY is processed before the SELECT list, so an alias such as yr is unknown there and raises error 207. Repeat the expression, for example GROUP BY YEAR(order_date).

Is adding a column to GROUP BY always safe?

Only if it has one value per existing group. If it varies, the query returns more rows than before. Check first, or aggregate the column instead.

Learn more on CodeWithSQL

Official documentation

Last technically reviewed 23 October 2026; examples and diagnostics run on SQL Server 2025 (17.0.1145.4). Message text checked against the engine's sys.messages catalogue.

Still stuck on a SQL Server error?

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