Skip to content

HAVING Clause

Difficulty: Basic
Generated on: 2025-07-10 02:23:33
Category: SQL Cheatsheet for Database Development


SQL HAVING Clause Cheatsheet (Basic Level)

Section titled “SQL HAVING Clause Cheatsheet (Basic Level)”

The HAVING clause is used in SQL to filter the results of a GROUP BY query. Unlike the WHERE clause, which filters rows before grouping, the HAVING clause filters groups after they’ve been formed. Essentially, it’s a WHERE clause for groups.

When to Use:

  • You need to filter based on aggregate functions (e.g., COUNT, SUM, AVG, MIN, MAX) calculated for groups.
  • You want to restrict the results to groups that meet specific criteria based on their aggregated values.
SELECT column1, column2, aggregate_function(column3)
FROM table_name
WHERE condition -- Optional: Filters rows before grouping
GROUP BY column1, column2
HAVING condition_on_aggregate_function;

Example:

SELECT department, COUNT(*) AS employee_count
FROM employees
GROUP BY department
HAVING COUNT(*) > 10; -- Filter departments with more than 10 employees
  • Finding groups exceeding a certain size: HAVING COUNT(*) > X
  • Filtering groups based on the sum of values: HAVING SUM(column) > Y
  • Identifying groups with an average value above a threshold: HAVING AVG(column) > Z
  • Selecting groups with a minimum or maximum value within a range: HAVING MIN(column) > A AND MAX(column) < B
  • Reporting on departments with a total salary greater than a certain amount.
  • Finding customers who have placed more than a certain number of orders.
  • Use WHERE before GROUP BY whenever possible: WHERE filters rows before grouping, which is generally more efficient than filtering groups with HAVING. Reduce the dataset as early as possible.
  • Minimize the complexity of HAVING conditions: Complex conditions can impact performance. Consider using subqueries or Common Table Expressions (CTEs) to simplify logic.
  • Index relevant columns: Ensure that columns used in GROUP BY and HAVING clauses are indexed for faster retrieval.
  • Understand the execution plan: Use your database’s query execution plan tool (e.g., EXPLAIN in MySQL, EXPLAIN ANALYZE in PostgreSQL, “Display Estimated Execution Plan” in SQL Server Management Studio) to identify potential performance bottlenecks.
  • Avoid using HAVING without GROUP BY: While some databases allow it (effectively turning it into a WHERE clause on the entire result set), it’s generally bad practice and can be confusing.

Sample Data:

Let’s say we have a table called orders:

order_idcustomer_idorder_datetotal_amount
11012023-01-15150.00
21022023-02-20200.00
31012023-03-10100.00
41032023-04-05300.00
51022023-05-12250.00
61012023-06-01120.00
71042023-07-18180.00
81032023-08-25350.00
91022023-09-07220.00

Example 1: Customers with total order amounts greater than $500

SELECT customer_id, SUM(total_amount) AS total_spent
FROM orders
GROUP BY customer_id
HAVING SUM(total_amount) > 500;

Output:

customer_idtotal_spent
102670.00
103650.00

Example 2: Customers who placed more than 2 orders

SELECT customer_id, COUNT(*) AS order_count
FROM orders
GROUP BY customer_id
HAVING COUNT(*) > 2;

Output:

customer_idorder_count
1013
1023

Example 3: Customers whose average order amount is greater than $200

SELECT customer_id, AVG(total_amount) AS average_order
FROM orders
GROUP BY customer_id
HAVING AVG(total_amount) > 200;

Output:

customer_idaverage_order
103325.00

Example 4: Combining WHERE and HAVING

Find customers who placed orders after 2023-01-01 and whose total spending is greater than $400.

SELECT customer_id, SUM(total_amount) AS total_spent
FROM orders
WHERE order_date > '2023-01-01' -- Filter orders before grouping
GROUP BY customer_id
HAVING SUM(total_amount) > 400; -- Filter groups after grouping
  • Using HAVING without GROUP BY (usually incorrect): Avoid this. If you’re not grouping, use WHERE.
  • Confusing WHERE and HAVING: Remember that WHERE filters rows before grouping, and HAVING filters groups after grouping.
  • Incorrectly referencing non-grouped columns in HAVING: The HAVING clause should generally only reference aggregate functions or columns included in the GROUP BY clause. Referencing other columns can lead to unpredictable results or errors.
  • Performance issues with complex HAVING clauses: Simplify complex conditions or consider using CTEs or subqueries to improve performance.
  • Case-sensitivity issues: Ensure that column names and string comparisons in the HAVING clause are case-sensitive (or insensitive) according to your database’s configuration.

Troubleshooting:

  • Unexpected results: Double-check your GROUP BY clause and the aggregate functions used in the HAVING clause. Make sure they accurately reflect the logic you’re trying to implement.
  • Error messages: Pay close attention to error messages. They often provide clues about syntax errors or incorrect column references.
  • Performance problems: Use your database’s query execution plan tool to identify bottlenecks. Consider adding indexes or rewriting the query to improve performance.

While the basic syntax of the HAVING clause is generally consistent across different SQL databases, there might be subtle differences in specific functions or behaviors.

  • MySQL: MySQL allows referencing non-aggregated columns in the HAVING clause without including them in the GROUP BY clause (if ONLY_FULL_GROUP_BY is disabled). This is generally considered bad practice and can lead to unpredictable results. It’s recommended to enable ONLY_FULL_GROUP_BY to enforce stricter SQL standards.
  • PostgreSQL: PostgreSQL enforces stricter SQL standards and requires that all non-aggregated columns in the SELECT list and HAVING clause be included in the GROUP BY clause.
  • SQL Server: SQL Server follows ANSI SQL standards and requires that all non-aggregated columns in the SELECT list and HAVING clause be included in the GROUP BY clause.
  • Oracle: Oracle also adheres to ANSI SQL standards and requires that all non-aggregated columns in the SELECT list and HAVING clause be included in the GROUP BY clause.

Key Takeaway: Always consult the documentation for your specific database system to understand any specific nuances or limitations related to the HAVING clause. Enable strict SQL modes (where available) to enforce standard SQL behavior and avoid potential issues.