WHERE vs HAVING
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
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.

