WHERE vs HAVING
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
WHERE and HAVING both filter data in SQL, but they operate at different stages of a query. WHERE filters rows before grouping and aggregation, while HAVING filters groups after aggregation has already happened.
The Core Difference
Think about the query pipeline this way:
- rows are read from tables
WHEREremoves rows you do not want- remaining rows may be grouped
- aggregates such as
COUNTorSUMare computed HAVINGremoves groups you do not want
That is why the two clauses are not interchangeable even though they both feel like filters.
WHERE Filters Individual Rows
Use WHERE when the condition is about raw row values.
This filters rows before any grouping takes place.
Another example:
Again, the condition applies to each row individually.
HAVING Filters Aggregated Groups
Use HAVING when the condition depends on aggregate results.
This does not ask whether an individual row has count >= 10. It asks whether the group formed by each department has at least ten rows.
That is why HAVING comes after GROUP BY.
A Query That Uses Both
Many real queries use both clauses together.
Interpretation:
- '
WHERE active = 1keeps only active employees' - '
GROUP BY departmentbuilds department groups' - '
HAVING AVG(salary) > 50000keeps only departments whose average salary is above the threshold'
This is a good example because it shows each clause doing a different job.
Why WHERE Is Usually Better For Non-Aggregate Conditions
If a condition can be written in WHERE, it usually should be. That lets the database reduce the number of rows earlier in the execution pipeline, which is often better for performance and clarity.
For example, this is usually the right form:
Instead of trying to push the row-level condition into HAVING unnecessarily.
Filtering earlier means fewer rows need to be grouped and aggregated.
Common Beginner Mistake
A very common mistake is trying to write aggregate conditions in WHERE.
That fails because COUNT(*) does not exist at the row-filtering stage.
The correct version is:
HAVING Without GROUP BY
Some SQL dialects allow HAVING without an explicit GROUP BY, especially when the whole result is treated as one aggregate group.
Example:
This is valid in some systems, but conceptually it is still filtering an aggregate result, not row data.
That is why the main rule still holds: HAVING is about aggregates.
Performance Perspective
A simple rule of thumb is:
- put row predicates in
WHERE - put aggregate predicates in
HAVING
This is not just style. It aligns with how the database engine can optimize work.
If you move a row predicate into HAVING, the database may have to group more rows than necessary before discarding them.
Common Pitfalls
- Using
HAVINGwhen the condition is really about raw rows and belongs inWHERE. - Trying to use aggregate functions such as
COUNT()directly inWHERE. - Thinking
WHEREandHAVINGare interchangeable because both filter results. - Forgetting that
HAVINGruns after grouping, so it cannot reduce pre-group row count the same wayWHEREcan. - Writing harder-to-read queries by mixing row-level and group-level logic in the wrong clause.
Summary
- '
WHEREfilters rows before grouping and aggregation.' - '
HAVINGfilters groups after aggregation.' - Use
WHEREfor row-level conditions andHAVINGfor aggregate conditions. - Queries often use both clauses together for different parts of the logic.
- If a predicate can be applied before grouping,
WHEREis usually the better place for it.
Related reading
- Which annotation should I use IdClass or EmbeddedId
- Which data structures to use when storing multiple entities with multiple query criteria?
- Which database for a web crawler, and how do I use MySQL in a distributed environment?
- Which distributed SQL databases put data from different tables with the same tenant in the same node?
- Which is faster multiple single INSERTs or one multiple-row INSERT?
- Which is fastest? SELECT SQL_CALC_FOUND_ROWS FROM table, or SELECT COUNT
- Which is more efficient Multiple MySQL tables or one large table?
- Which MySQL data type to use for storing boolean values

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.