How to Fix “Column Is Invalid in the Select List” in SQL Server

The error “Column is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause” appears when a query uses GROUP BY but also selects a column that SQL Server cannot reduce to a single value for each group.

In simple terms, once rows are grouped, SQL Server can only return:

  • columns included in the GROUP BY clause, or
  • columns summarized with an aggregate function such as SUM(), AVG(), COUNT(), MIN(), or MAX().

If a selected column is neither grouped nor aggregated, SQL Server does not know which single value to show for that group, so it throws this error.

What This Error Means?

GROUP BY is used when you want to summarize rows. For example, you might want:

  • the average salary for each department
  • the number of people in each state
  • the highest sale in each category

When SQL Server groups rows, it combines multiple records into one result row per group. Because of that, every selected value must either identify the group or summarize the rows inside it.

You can think of it as split, apply, combine:

  • Split: divide rows into groups
  • Apply: run an aggregate function on each group
  • Combine: return one row per group
Split apply combine strategy sample
“SPLIT_APPLY_COMBINE” strategy sample

In the figure above, values in column C1 are grouped, an aggregate function is applied to each group, and one result row is returned for each group.

How to Fix the Error?

There are two logical ways to fix this error.

Fix 1: Add the column to the GROUP BY clause
Use this when you want separate results for each distinct value of that column.

Fix 2: Wrap the column in an aggregate function
Use this when you want one summarized value per group.

In most cases, the second option is what you actually want, because the purpose of GROUP BY is usually to summarize data.

Example 1: Grouping Employee Salaries

Here is an example using a database named appuals.

Database creation
Database creation

Create a table called employee:

USE [appuals]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[employee](
    [e_id] [int] NOT NULL,
     NULL,
    [dep_id] [int] NULL,
    [salary] [int] NULL,
    CONSTRAINT [PK_employee] PRIMARY KEY CLUSTERED
    (
        [e_id] ASC
    )
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
Employee table creation
Employee table creation

Insert sample data:

INSERT INTO employee(e_id, e_ename, dep_id, salary)
VALUES
(101, 'Sadia', 1, 6000),
(102, 'Saba', 1, 5000),
(103, 'Sana', 2, 4000),
(104, 'Hammad', 2, 3000),
(105, 'Umer', 3, 4000),
(106, 'Kanwal', 3, 2000)
Data insertion into employee table
Data insertion into table “employee”

To view all rows:

SELECT * FROM employee
Output from the employee table
The output from the employee table

Wrong Query

SELECT dep_id, salary
FROM employee
GROUP BY dep_id

Error: Column ’employee.salary’ is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Column employee.salary is invalid in the select list
Error: Column ’employee.salary’ is invalid in the select list

Why it fails: the query groups by dep_id, but salary is not grouped and not aggregated. Since one department can have multiple salary values, SQL Server cannot choose just one salary to return.

Correct Query

SELECT dep_id, AVG(salary) AS average_salary
FROM employee
GROUP BY dep_id

Why this works: AVG(salary) summarizes all salary values inside each department, so SQL Server can return one row per department with one calculated result.

Average salary of employees in each department
Find the average salary of employees in each department

This follows the same split, apply, combine pattern shown below:

Split apply combine strategy applied on employee table
SPLIT-APPLY-COMBINE strategy applied on employee table

Common Aggregate Functions

These are the most common functions used with GROUP BY:

  • SUM() returns the total for each group.
  • COUNT() returns the number of rows in each group.
  • AVG() returns the average value in each group.
  • MIN() returns the smallest value in each group.
  • MAX() returns the largest value in each group.

Example 2: Counting People by State

Now let’s look at another practical example.

Create a table named people:

USE [appuals]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[people](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
     NULL,
     NULL,
     NULL,
    [age] [int] NULL
) ON [PRIMARY]
GO
People table creation
Table creation

Insert sample data:

INSERT INTO people(name, city, state, age)
VALUES
('Meggs', 'MONTEREY', 'CA', 20),
('Staton', 'HAYWARD', 'CA', 22),
('Irons', 'IRVINE', 'CA', 25),
('Krank', 'PLEASANT', 'IA', 23),
('Davidson', 'WEST BURLINGTON', 'IA', 40),
('Pepewachtel', 'FAIRFIELD', 'IA', 35),
('Schmid', 'HILLSBORO', 'OR', 23),
('Davidson', 'CLACKAMAS', 'OR', 40),
('Condy', 'GRESHAM', 'OR', 35)
Data insertion into people table
Data insertion into “people” table

Correct Query

Suppose you want to find the number of residents and the average age for each state:

SELECT state, AVG(age) AS Age, COUNT(*) AS no_of_residents
FROM people
GROUP BY state

Why this works: state identifies each group, while AVG(age) summarizes ages and COUNT(*) counts rows within that state.

Number of residents and average age by state
Result: number of residents and average age by state

Wrong Query

SELECT state, age, COUNT(*) AS no_of_residents
FROM people
GROUP BY state

Error: Column ‘people.age’ is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Grouping by state causes an error

Why it fails: one state can contain many people with different ages, so SQL Server cannot return a single age value unless you either group by it or summarize it.

Logical Fix

SELECT state, AVG(age) AS Age, COUNT(*) AS no_of_residents
FROM people
GROUP BY state

This returns one row per state along with the average age and resident count for that state.

Important GROUP BY Rules

  • GROUP BY comes after WHERE and before ORDER BY.
  • Use WHERE to filter rows before grouping.
  • Every selected column must be either grouped or aggregated.
  • NULL values are treated as one group.

GROUP BY with NULL Values

A real NULL is not the same as an empty string , and it is also not the same as the text ‘NULL’. SQL Server treats them differently.

First, insert a row with an empty string in the state column:

INSERT INTO people(name, city, state, age)
VALUES ('Kanwal', 'GRESHAM', '', 35)
Adding empty value to state column for GROUP BY
Adding an empty value to the column for GROUP BY

Now run:

SELECT state, AVG(age) AS Age, COUNT(*) AS no_of_residents
FROM people
GROUP BY state
Empty value in the column is treated as a single group
Empty value in the column is considered a single group

The empty string is treated as its own group.

Now insert actual NULL values:

INSERT INTO people(name, city, state, age)
VALUES
('Kanwal', 'IRVINE', NULL, 35),
('Krank', 'PLEASANT', NULL, 23)
Inserting NULL values in the state column for GROUP BY
Inserting NULL values in the column for GROUP BY

Run the same query again:

SELECT state, AVG(age) AS Age, COUNT(*) AS no_of_residents
FROM people
GROUP BY state
NULL values in the column are treated as a single group
NULL values in the column are treated as a single group

All real NULL values are grouped together as one group. By contrast, the text ‘NULL’ would be treated as an ordinary string value.

ABOUT THE AUTHOR

Kevin Arrows


Kevin Arrows is a highly experienced and knowledgeable technology specialist with over a decade of industry experience. He holds a Microsoft Certified Technology Specialist (MCTS) certification and has a deep passion for staying up-to-date on the latest tech developments. Kevin has written extensively on a wide range of tech-related topics, showcasing his expertise and knowledge in areas such as software development, cybersecurity, and cloud computing. His contributions to the tech field have been widely recognized and respected by his peers, and he is highly regarded for his ability to explain complex technical concepts in a clear and concise manner.