datarekha
SQL Medium Asked at GoogleAsked at Amazon

Can you GROUP BY a derived expression or a SELECT alias, and how does this differ across databases?

The short answer

You can always GROUP BY a derived expression written directly. Whether you can reference a SELECT alias in GROUP BY depends on the database: MySQL and BigQuery allow it, while PostgreSQL and SQL Server do not because aliases are not resolved until after GROUP BY in the logical order.

How to think about it

This is another logical execution order question wearing a different hat. The fact it rests on: GROUP BY is evaluated before SELECT, so a SELECT alias doesn’t exist yet when GROUP BY runs — at least in the engines that follow the standard strictly.

Grouping by an expression — always works

Write the expression out fully in GROUP BY and it works everywhere, no exceptions. Here we collapse daily orders into months by slicing the date string:

SELECT substr(order_date, 1, 7) AS month,
       SUM(revenue) AS total_revenue,
       COUNT(*)     AS order_count
FROM orders
GROUP BY substr(order_date, 1, 7)   -- the expression repeated, not the alias
ORDER BY month;
monthtotal_revenueorder_count
2024-012502
2024-024502
2024-034802

Three months, two orders each, revenue summed within each — and it runs identically on PostgreSQL, MySQL, BigQuery, and SQL Server because nothing depends on alias resolution.

Grouping by a SELECT alias — engine-dependent

This is where portability breaks. Lenient engines let you name the alias in GROUP BY; strict ones reject it, because at GROUP BY time the alias hasn’t been defined yet:

-- Works in MySQL and BigQuery; ERRORS in PostgreSQL and SQL Server:
SELECT substr(order_date, 1, 7) AS month, SUM(revenue)
FROM orders
GROUP BY month;        -- PostgreSQL: column "month" does not exist

The portable fix is to repeat the expression (as above) or push it into a subquery so the alias is a real column by the time you group:

SELECT month, SUM(revenue)
FROM (
  SELECT substr(order_date, 1, 7) AS month, revenue FROM orders
) sub
GROUP BY month;        -- now 'month' is a genuine column, portable everywhere

Grouping by column position — avoid it

GROUP BY 1 means “group by the first SELECT column.” Most engines accept it, but it’s brittle: reorder your SELECT list and the grouping changes silently, with no error to catch it.

-- 'GROUP BY 1' is GROUP BY country today; add a column before it and it breaks quietly
SELECT country, SUM(revenue) FROM orders GROUP BY 1;
Learn it properly Aggregates & GROUP BY

Keep practising

All SQL questions

Explore further

Skip to content