SQL HAVING Clause | Complete Guide with Examples Part 1

SQL HAVING Clause

The SQL HAVING Clause is used to filter grouped data after the GROUP BY operation has been performed. While the WHERE clause filters individual rows before grouping, the HAVING clause filters entire groups based on specified conditions. It is one of the most important clauses for creating analytical reports and summaries in SQL.

In real-world databases, organizations often need reports such as departments having more than 50 employees, product categories generating sales above a certain amount, or courses having an average score greater than a specific value. Such conditions cannot be handled directly by the WHERE clause because they depend on aggregate calculations. The HAVING clause solves this problem efficiently.

Understanding HAVING is essential for students, database developers, data analysts, and anyone involved in data reporting because it enables advanced filtering of summarized information.


What is the HAVING Clause?

The HAVING clause is used to specify conditions on groups created by the GROUP BY clause. It allows aggregate functions such as COUNT(), SUM(), AVG(), MIN(), and MAX() to be used in filtering conditions.

Without HAVING, SQL would return all groups generated by GROUP BY. HAVING helps display only the groups that satisfy specific requirements.


Why is HAVING Important?


Basic Syntax of HAVING Clause

SELECT column_name,
aggregate_function(column_name)

FROM table_name

GROUP BY column_name

HAVING condition;

The HAVING condition is evaluated after grouping is completed.


Sample Student Table

StudentID StudentName Course Marks
101 Rahul BCA 80
102 Priya BCA 90
103 Amit MCA 75
104 Neha MCA 85
105 Rohan B.Tech 88

HAVING with COUNT()

COUNT() is frequently used with HAVING to identify groups containing a specific number of records.

Example

SELECT Course,
COUNT(*) AS TotalStudents

FROM Student

GROUP BY Course

HAVING COUNT(*) > 1;

Output

Course TotalStudents
BCA 2
MCA 2

Only courses having more than one student are displayed.


HAVING with SUM()

The SUM() function calculates total values for each group, and HAVING filters groups based on those totals.

Sales Table Example

Category SalesAmount
Electronics 5000
Electronics 7000
Books 3000
SELECT Category,
SUM(SalesAmount) AS TotalSales

FROM Sales

GROUP BY Category

HAVING SUM(SalesAmount) > 5000;

The query displays categories whose total sales exceed 5000.


HAVING with AVG()

AVG() calculates average values for each group, and HAVING can filter based on those averages.

Example

SELECT Course,
AVG(Marks) AS AverageMarks

FROM Student

GROUP BY Course

HAVING AVG(Marks) > 80;

Only courses having an average score greater than 80 are displayed.


HAVING with MIN()

MIN() returns the smallest value within each group.

SELECT Course,
MIN(Marks) AS LowestMarks

FROM Student

GROUP BY Course

HAVING MIN(Marks) > 70;

This query shows only those courses where the minimum mark is above 70.


HAVING with MAX()

MAX() returns the highest value within a group.

SELECT Course,
MAX(Marks) AS HighestMarks

FROM Student

GROUP BY Course

HAVING MAX(Marks) > 85;

Only courses having maximum marks greater than 85 appear in the output.


Difference Between WHERE and HAVING

Many beginners confuse HAVING with WHERE. Although both are used for filtering, they operate at different stages of query execution.

WHERE HAVING
Filters individual rows Filters groups
Executes before GROUP BY Executes after GROUP BY
Cannot directly use aggregate functions Can use aggregate functions
Works on raw records Works on summarized data

Execution Order in SQL

To understand HAVING properly, it is important to know the order in which SQL processes queries.

  1. FROM
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. SELECT
  6. ORDER BY

Since HAVING executes after GROUP BY, it can evaluate aggregate results.


Practical Example: Employee Database

EmployeeName Department Salary
Amit IT 50000
Neha IT 60000
Rahul HR 45000

Department Salary Analysis

SELECT Department,
AVG(Salary) AS AverageSalary

FROM Employee

GROUP BY Department

HAVING AVG(Salary) > 50000;

The query displays only departments with an average salary greater than 50000.


Practical Example: College Management System

SELECT Course,
COUNT(*) AS TotalStudents

FROM Student

GROUP BY Course

HAVING COUNT(*) >= 50;

This report helps administrators identify courses with large student enrollments.


Practical Example: Online Shopping System

SELECT Category,
SUM(SalesAmount) AS TotalSales

FROM Orders

GROUP BY Category

HAVING SUM(SalesAmount) > 10000;

Management can focus on categories generating significant revenue.


Advantages of HAVING Clause


HAVING with Multiple Conditions

The HAVING clause can contain multiple conditions using logical operators such as AND, OR, and NOT. This allows developers to create highly specific reports based on aggregate results.

Example Using AND

SELECT Department,
COUNT(*) AS TotalEmployees,
AVG(Salary) AS AverageSalary

FROM Employee

GROUP BY Department

HAVING COUNT(*) > 10
AND AVG(Salary) > 50000;

This query displays departments that have more than 10 employees and an average salary greater than 50,000.


Example Using OR

SELECT Course,
COUNT(*) AS TotalStudents

FROM Student

GROUP BY Course

HAVING COUNT(*) > 100
OR COUNT(*) < 20;

This query returns courses with either very high enrollment or very low enrollment.


HAVING with Multiple Columns in GROUP BY

SQL allows grouping data using more than one column. HAVING can then be used to filter these grouped combinations.

Example

SELECT Department,
Designation,
COUNT(*) AS EmployeeCount

FROM Employee

GROUP BY Department, Designation

HAVING COUNT(*) > 5;

The query shows department-designation combinations that contain more than five employees.


HAVING with ORDER BY

After filtering grouped data using HAVING, the ORDER BY clause can sort the results.

Example

SELECT Category,
SUM(SalesAmount) AS TotalSales

FROM Sales

GROUP BY Category

HAVING SUM(SalesAmount) > 10000

ORDER BY TotalSales DESC;

The categories are displayed from highest sales to lowest sales.


HAVING with JOIN Operations

HAVING is often used together with JOIN statements when data is spread across multiple tables.

Department and Employee Tables

SELECT Department.DepartmentName,
COUNT(Employee.EmployeeID) AS TotalEmployees

FROM Department

INNER JOIN Employee

ON Department.DepartmentID =
Employee.DepartmentID

GROUP BY Department.DepartmentName

HAVING COUNT(Employee.EmployeeID) > 20;

This query displays departments having more than twenty employees.


HAVING with LEFT JOIN

HAVING can also be used with LEFT JOIN to analyze records that may not have matching values in another table.

SELECT Department.DepartmentName,
COUNT(Employee.EmployeeID) AS TotalEmployees

FROM Department

LEFT JOIN Employee

ON Department.DepartmentID =
Employee.DepartmentID

GROUP BY Department.DepartmentName

HAVING COUNT(Employee.EmployeeID) = 0;

This query finds departments that currently have no employees.


HAVING with Subqueries

Subqueries can be used inside HAVING conditions to create advanced comparisons and reports.

Example

SELECT Department,
AVG(Salary) AS AverageSalary

FROM Employee

GROUP BY Department

HAVING AVG(Salary) >
(
SELECT AVG(Salary)
FROM Employee
);

This query displays departments whose average salary is higher than the overall company average salary.


Advanced Example: Product Sales Analysis

SELECT Category,
SUM(SalesAmount) AS TotalSales

FROM Sales

GROUP BY Category

HAVING SUM(SalesAmount) >
(
SELECT AVG(SalesAmount)
FROM Sales
);

The report identifies categories performing above average.


HAVING with COUNT(DISTINCT)

COUNT(DISTINCT) is useful when unique values need to be analyzed.

Example

SELECT Department,
COUNT(DISTINCT Designation) AS UniqueDesignations

FROM Employee

GROUP BY Department

HAVING COUNT(DISTINCT Designation) > 3;

This query shows departments containing more than three unique job roles.


Real-World Example: University Management System

Universities often analyze course enrollment patterns.

SELECT Course,
COUNT(*) AS StudentCount

FROM Student

GROUP BY Course

HAVING COUNT(*) > 50;

Administrators can identify highly popular courses.


Real-World Example: Banking System

Banks frequently generate branch-wise reports.

SELECT BranchName,
SUM(AccountBalance) AS TotalBalance

FROM Accounts

GROUP BY BranchName

HAVING SUM(AccountBalance) > 1000000;

The report highlights branches with large customer deposits.


Real-World Example: E-Commerce Website

SELECT ProductCategory,
COUNT(*) AS ProductCount

FROM Products

GROUP BY ProductCategory

HAVING COUNT(*) > 100;

Store managers can identify categories with extensive product inventories.


Real-World Example: Hospital Management System

SELECT Department,
COUNT(*) AS PatientCount

FROM Patients

GROUP BY Department

HAVING COUNT(*) > 200;

Hospital administrators can identify departments with heavy patient loads.


Performance Optimization Tips

HAVING can become resource-intensive when working with large datasets. The following techniques help improve performance.


Why WHERE is Faster Than HAVING?

WHERE filters records before grouping begins, reducing the amount of data processed. HAVING filters data after grouping, meaning more records may need to be analyzed.

Whenever possible, row-level filtering should be performed using WHERE for better performance.


Common Errors While Using HAVING

1. Using HAVING Without Need

SELECT *
FROM Student
HAVING Marks > 60;

This is incorrect because HAVING is designed for grouped data.


2. Missing GROUP BY

Many beginners attempt to use HAVING without understanding how grouping works.


3. Incorrect Aggregate Logic

Using inappropriate aggregate functions can produce inaccurate reports.


4. Overcomplicated Conditions

Large HAVING clauses with multiple nested conditions can reduce readability and performance.


Advantages of HAVING Clause


Limitations of HAVING Clause


SQL HAVING Clause Interview Questions and Answers

1. What is the purpose of HAVING?

HAVING filters grouped data after aggregation.

2. What is the difference between WHERE and HAVING?

WHERE filters rows, while HAVING filters groups.

3. Which clause executes first?

WHERE executes before HAVING.

4. Can HAVING be used without GROUP BY?

Some databases allow it, but it is mainly used with GROUP BY.

5. Why is HAVING important?

It enables filtering based on aggregate results.

6. Can HAVING use COUNT()?

Yes.

7. Can HAVING use SUM()?

Yes.

8. Can HAVING use AVG()?

Yes.

9. Can HAVING use MIN()?

Yes.

10. Can HAVING use MAX()?

Yes.

11. Can HAVING work with JOIN?

Yes.

12. Can HAVING work with subqueries?

Yes.

13. What does HAVING COUNT(*) > 5 mean?

Only groups containing more than five rows are returned.

14. Which clause comes after GROUP BY?

HAVING.

15. Which clause usually comes after HAVING?

ORDER BY.

16. Can multiple conditions be used in HAVING?

Yes, using AND, OR, and NOT.

17. What is aggregate filtering?

Filtering based on calculated summary values.

18. Is HAVING slower than WHERE?

Generally yes, because it processes grouped results.

19. Can aliases be used with HAVING?

It depends on the database system.

20. What is the main advantage of HAVING?

It filters summarized data effectively.

21. Is HAVING useful in reporting?

Yes, it is widely used in reporting systems.

22. Can HAVING improve analytical queries?

Yes.

23. What type of data does HAVING filter?

Grouped and aggregated data.

24. Can HAVING be combined with ORDER BY?

Yes.

25. Why should developers learn HAVING?

It is essential for advanced SQL reporting and analytics.


Conclusion

The SQL HAVING Clause is a powerful feature used to filter grouped data after aggregate calculations have been performed. It plays a critical role in reporting, analytics, business intelligence, and decision-making systems.

By combining HAVING with GROUP BY, aggregate functions, JOINs, subqueries, and ORDER BY, developers can build advanced SQL reports that transform raw data into valuable business insights. Mastering the HAVING clause is an important step toward becoming proficient in SQL and database management.

← Previous: GROUP BY Next: DISTINCT →
Home Visit Our YouTube Channel