Lesson 67 of 12115 min read

WHERE vs HAVING in SQL: Difference with Examples

A focused, side-by-side comparison of WHERE and HAVING, reinforcing exactly when to use each and how they interact in the same query.

Author: CodersNexus

WHERE vs HAVING in SQL: Difference with Examples

The previous lesson introduced HAVING primarily in contrast to WHERE, but this distinction is important enough, and confusing enough for beginners, to deserve its own focused, comparative lesson. This lesson consolidates WHERE and HAVING side by side, with direct comparison tables and worked examples, functioning as a quick-reference specifically for this one, frequently tested concept.

Key Definitions

  • WHERE: A clause that filters individual rows before any grouping or aggregation occurs.
  • HAVING: A clause that filters groups after GROUP BY and aggregate functions have already been applied.
  • Row-level filter: A filtering condition, like WHERE, applied to individual, ungrouped rows.
  • Group-level filter: A filtering condition, like HAVING, applied to already-aggregated groups.

What You'll Learn

  • State the core difference between WHERE and HAVING clearly and confidently.
  • Identify, from a business question alone, whether it requires WHERE, HAVING, or both.
  • Use both WHERE and HAVING correctly together in a single, realistic query.
  • Avoid the classic beginner mistake of using WHERE where HAVING is required, or vice versa.

Detailed Explanation

The cleanest way to remember the difference between WHERE and HAVING is to ask: 'does this condition apply to individual rows, or to a computed group summary?' If the condition can be evaluated on a single row in isolation — such as 'salary greater than 50000' or 'hire_date after 2024-01-01' — it belongs in WHERE. If the condition can only be evaluated after rows have been grouped and summarized — such as 'total salary per department greater than 100000' or 'number of orders per customer greater than 5' — it belongs in HAVING.

A helpful test: if your condition contains an aggregate function name like SUM, COUNT, AVG, MIN, or MAX, it must go in HAVING, not WHERE. If your condition references a raw column value directly, without any aggregate function wrapping it, it belongs in WHERE, and using WHERE there will also generally be more efficient, since it reduces the data set before the more expensive grouping and aggregation work even begins.

When a query needs both types of filtering, WHERE should handle everything it possibly can first, since filtering out unnecessary rows early makes the subsequent GROUP BY and aggregation faster by working with a smaller data set. HAVING should then be reserved only for conditions that genuinely require the aggregated result to be evaluated, since it cannot be run earlier by definition.

Visual Summary

Draw a simple two-column decision flowchart. Left column: 'Does your condition reference SUM, COUNT, AVG, MIN, or MAX?' with a 'No' arrow leading to a box labeled 'Use WHERE' and a 'Yes' arrow leading to a box labeled 'Use HAVING'. Below both boxes, add a note: 'For best performance, let WHERE filter as much as possible before grouping; reserve HAVING only for conditions that truly need the aggregated value.'

Quick Reference

Business QuestionRequired ClauseReason
Employees hired after 2024WHEREFilters individual rows on a raw column value
Departments with total salary over 100000HAVINGRequires the aggregated SUM per department
Orders placed in the last 30 daysWHEREFilters individual rows on a raw date value
Customers with more than 5 ordersHAVINGRequires the aggregated COUNT per customer
Active employees, in departments with total salary over 100000Both WHERE and HAVINGWHERE filters active employees first; HAVING then filters aggregated department totals

SQL Example

-- WHERE only: filtering individual rows, no aggregation involved
SELECT * FROM employees
WHERE hire_date >= '2024-01-01';

-- HAVING only: filtering based on an aggregated value
SELECT department_id, SUM(salary) AS total_salary
FROM employees
GROUP BY department_id
HAVING SUM(salary) > 100000;

-- WHERE and HAVING together
SELECT department_id, SUM(salary) AS total_salary
FROM employees
WHERE is_active = TRUE
GROUP BY department_id
HAVING SUM(salary) > 100000;

The first query needs only WHERE, since 'hired after a certain date' is a condition evaluable on individual rows. The second query needs only HAVING, since 'total salary over 100000' can only be evaluated after grouping and summing. The third query combines both: WHERE first filters down to only active employees, and HAVING then filters departments based on the total salary calculated from just those active employees, demonstrating the standard, efficient pattern of filtering rows early and groups afterward.

Real-World Examples

  • Every real-world analytics query that combines a data-quality filter (WHERE, such as excluding test accounts) with a business threshold (HAVING, such as minimum spend) demonstrates this exact WHERE-then-HAVING pattern.
  • Financial reporting systems commonly use WHERE to exclude cancelled transactions before using HAVING to flag departments exceeding budget thresholds based on only their valid transactions.
  • Marketing platforms use WHERE to filter to a specific campaign date range before using HAVING to identify customer segments with an aggregated engagement score above a target.
  • HR systems use WHERE to filter to current employees before using HAVING to flag departments with an average salary below a benchmark.
  • E-commerce systems use WHERE to exclude refunded orders before using HAVING to identify top customers by total valid, non-refunded spend.

Common Mistakes to Avoid

  • Placing an aggregate-based condition in WHERE, resulting in a query error since aggregates aren't available at that stage.
  • Placing a simple row-level condition in HAVING unnecessarily, which works but is less efficient than using WHERE.
  • Forgetting that WHERE should generally run first to reduce data before the more expensive aggregation step that HAVING depends on.
  • Assuming WHERE and HAVING are interchangeable in every scenario, rather than recognizing their genuinely distinct, non-overlapping roles.

Interview Questions

Q1. What is the single clearest rule to decide between WHERE and HAVING?

If the condition references an aggregate function like SUM, COUNT, AVG, MIN, or MAX, it must go in HAVING. If it references a raw column value directly without any aggregate function, it belongs in WHERE.

Q2. Why is it more efficient to filter with WHERE before HAVING whenever possible?

WHERE reduces the number of rows before the more computationally expensive grouping and aggregation work begins, meaning less data needs to be processed overall, whereas HAVING can only filter after that aggregation work has already been done.

Q3. Give an example of a query that legitimately needs both WHERE and HAVING.

A report showing 'departments with total salary over 100000, considering only active employees' needs WHERE to filter for active employees first, and then HAVING to filter departments based on the total salary calculated from just those active employees.

Q4. Is it ever technically possible to write a HAVING-only condition using WHERE instead?

No, not if the condition genuinely depends on an aggregated value across multiple rows, since WHERE has no access to aggregate function results at the point it executes; only HAVING can evaluate conditions based on already-computed group aggregates.

Practice MCQs

1. A condition like 'salary > 50000' on individual employee rows belongs in:

  1. HAVING
  2. WHERE
  3. GROUP BY
  4. ORDER BY

Answer: B. WHERE

Explanation: This condition can be evaluated directly on a single row without needing any aggregation, making WHERE the correct and more efficient choice.

2. A condition like 'SUM(salary) > 100000' belongs in:

  1. WHERE
  2. HAVING
  3. SELECT only
  4. FROM

Answer: B. HAVING

Explanation: Since this condition depends on an aggregated SUM value computed per group, only HAVING can evaluate it, as WHERE executes before aggregation occurs.

3. For query performance, it is generally best to:

  1. Put every condition in HAVING
  2. Filter as much as possible with WHERE before using HAVING for aggregate-based conditions
  3. Avoid using WHERE entirely
  4. Always use both clauses even if only one is needed

Answer: B. Filter as much as possible with WHERE before using HAVING for aggregate-based conditions

Explanation: Filtering rows early with WHERE reduces the data set before the more expensive grouping and aggregation steps, improving overall query efficiency.

4. Which of the following requires HAVING rather than WHERE?

  1. Orders placed in the last 7 days
  2. Employees in the Engineering department
  3. Customers who placed more than 3 orders
  4. Products priced above 500

Answer: C. Customers who placed more than 3 orders

Explanation: Counting orders per customer requires aggregation (COUNT), and filtering on that aggregated count requires HAVING, unlike the other options which filter directly on raw row values.

Quick Revision Points

  • WHERE filters individual rows before grouping; HAVING filters groups after aggregation.
  • Any condition referencing SUM, COUNT, AVG, MIN, or MAX must use HAVING, not WHERE.
  • Combining WHERE and HAVING in one query is a standard, efficient pattern: WHERE narrows rows first, HAVING then filters groups.
  • This WHERE vs HAVING distinction is among the most frequently asked conceptual SQL interview questions.

Conclusion

  • The presence of an aggregate function in a condition is the clearest signal that HAVING, not WHERE, is required.
  • WHERE should always handle as much filtering as possible before HAVING, for both correctness and performance.
  • WHERE and HAVING are not interchangeable; each has a distinct, non-overlapping role in query execution.
  • This distinction, while simple once understood, remains one of the most commonly tested SQL fundamentals.

WHERE filters individual rows before any grouping or aggregation occurs, while HAVING filters entire groups after GROUP BY and aggregate functions have already been computed. The clearest test for which to use is whether the condition references an aggregate function like SUM or COUNT — if so, it must go in HAVING; otherwise, WHERE is both correct and more efficient. Combining both in a single query, with WHERE narrowing rows first and HAVING filtering the resulting aggregated groups afterward, is the standard, performant pattern used throughout real-world SQL reporting.

Frequently Asked Questions

Ask whether your condition involves an aggregate function like SUM, COUNT, or AVG. If yes, use HAVING. If the condition is about a raw column value on individual rows, use WHERE.

Technically it may work in some cases, but it is considered poor practice and less efficient, since HAVING filters after the more expensive grouping and aggregation steps have already run, doing unnecessary extra work compared to filtering early with WHERE.

WHERE executes before any grouping or aggregation happens, so COUNT(*) has no computed value yet at that stage. You need to move this condition into a HAVING clause, which executes after aggregation and can correctly evaluate COUNT(*).

WHERE is always evaluated first, filtering the raw rows down to a smaller set. GROUP BY and aggregate functions are then applied to that filtered set, and HAVING filters the resulting aggregated groups afterward.

Yes, if every filtering condition in the query depends on an aggregated value, such as 'show only departments with more than 10 employees,' the query may only need GROUP BY and HAVING, with no WHERE clause required at all.