Start studying
Module 5 · SQL Module contents
Module 5  ·  Card 8 / 14intermediate

Filtering Groups with HAVING

The HAVING clause filters aggregated summary groups created by a GROUP BY clause, rather than individual raw rows.

Because the WHERE clause filters rows before aggregation occurs, it cannot evaluate conditions on aggregate functions.

HAVING runs after aggregation, allowing you to test conditions like total revenue or average order size across groups.

For example, HAVING COUNT(*) > 10 keeps only departments with more than 10 sales.

Knowing the operational sequence of SQL ensures you place row-level filters in WHERE and group-level filters in HAVING.

Learn in depth ↓
Module 05 · SQL · 14 concepts
In depth  /  15 lines

Filtering Groups with HAVING, in more detail

The HAVING clause specifies conditional criteria that filter the summary groups produced by a GROUP BY clause.

It exists because the standard SQL query processing pipeline evaluates the WHERE clause before aggregation occurs.

Because WHERE executes prior to row grouping, it cannot reference aggregate metrics like sums, counts, or averages.

The HAVING clause executes after grouping and aggregation are complete, providing a filter on the resulting summary rows.

For example, filtering for departments where total sales exceed fifty thousand pounds requires a HAVING condition on SUM of sales.

Conditions inside HAVING can reference any aggregate function, regardless of whether that function appears in the SELECT clause.

While HAVING can technically evaluate unaggregated columns, doing so is poor practice and should be handled in WHERE.

Filtering rows in WHERE before grouping is computationally more efficient, as it shrinks the volume of data entering aggregation.

A query can contain both WHERE and HAVING clauses simultaneously, working at distinct stages of execution.

In such queries, WHERE eliminates unwanted raw rows first, GROUP BY aggregates the survivors, and HAVING filters the groups.

For instance, filtering orders from twenty twenty-four in WHERE and filtering customers with over five orders in HAVING.

Neglecting to use WHERE for row-level filters forces the database to aggregate unnecessary records, wasting memory and processing time.

The conceptual execution order of SQL is FROM, followed by WHERE, GROUP BY, HAVING, SELECT, and finally ORDER BY.

Remembering this execution lifecycle clarifies why column aliases created in SELECT cannot be referenced inside HAVING.

Analysts should always place row predicates in WHERE and reserve HAVING strictly for conditions that require aggregate metrics.

Want the full technical article? Wikipedia ↗
Test yourself

One question on this card. Every option explains itself once you pick, right or wrong.

Question 1
An analyst wants to list customer cities that have generated more than 100,000 pounds in total sales. Where does this condition belong?
SQL

14 concepts in this module, then a graded test with every answer explained.

Study this module →
↑↓ move↵ openesc close