I was attempting to write an ad-hoc query which aggregated some data using the GROUP BY clause for a quick data check when a copy-paste error made me stumble upon the following error:
Msg 164, Level 15, State 1, Line 8
Each GROUP BY expression must contain at least one column that is not an outer reference.
The query that returned the error looked like:
USE AdventureWorks2008R2 ;
GO
DECLARE @accountNumber VARCHAR(30) = '10-4020-000676'
SELECT YEAR(OrderDate) AS PurchaseYear,
@accountNumber AS AccountNumber,
SUM(TotalDue) AS TotalPurchase
FROM Sales.SalesOrderHeader
WHERE AccountNumber = @accountNumber
GROUP BY YEAR(OrderDate),
@accountNumber ;
GO
What I typically do when I work with the group by clause is that I take the columns from the SELECT clause, remove the aggregations and use that list for the GROUP BY clause. In that process, I ended up with a variable (@accountNumber) in the GROUP BY list. A variable is ultimately an expression which was treated by SQL Server as an outer reference – which is not allowed in T-SQL. The solution therefore is to change the list for the GROUP BY to not use variables.
USE AdventureWorks2008R2 ;
GO
DECLARE @accountNumber VARCHAR(30) = '10-4020-000676';
SELECT YEAR(OrderDate) AS PurchaseYear,
@accountNumber AS AccountNumber,
SUM(TotalDue) AS TotalPurchase
FROM Sales.SalesOrderHeader
WHERE AccountNumber = @accountNumber
GROUP BY YEAR(OrderDate),
AccountNumber ; --Notice that the variable has been replaced
--with the corresponding field name
GO
[Edit – 02/16/2014 – 01:20AM IST]:
Based on a couple of comments that I received on this post, I would like to elaborate further on the behaviour that is exhibited by SQL Server.
- The GROUP BY clause can operate on any expressions except single-row, single-column sub-queries
- This expression must contain at least one column belonging to the tables referenced in the FROM clause of the statement where GROUP BY is being applied
- A variable is a single-row, single-column expression (SELECT @accountNumber is perfectly valid), and does not reference any column from the tables used in the statement – this is what makes the variable invalid in the GROUP BY clause
Until we meet next time,

