# HAVING and Aggregate Functions This document details the strategic application of the SQL `HAVING` clause and core aggregate functions. Mastery enables developers to write high-impact queries that efficiently process and filter grouped data, a critical requirement for performant applications. Unlike the `WHERE` clause, which filters individual rows * before* grouping and aggregation, `HAVING` operates on grouped data *after* these operations have occurred. This distinction is fundamental for filtering based on aggregate results. ## Syntax The `HAVING` clause is applied after `GROUP BY` and before `ORDER BY`. ```sql SELECT column_name(s) FROM table_name WHERE condition -- Filters individual rows (optional) GROUP BY column_name(s) -- Groups rows with identical values HAVING condition -- Filters groups based on aggregate results ORDER BY column_name(s); -- Sorts the final result set (optional) ``` The `HAVING` condition typically involves one or more aggregate functions and comparison/logical operators. ## Aggregate Functions SQL aggregate functions transform a collection of values from multiple rows into a single summary value. They are indispensable for data analysis, reporting, and gaining insights from datasets. These functions operate on a set of values, not individual data points. ## Core Aggregate Functions | Function | Description | Application | | :------- | :----------------------------------------------------- | :-------------------------------------- | | `AVG()` | Calculates the average value of a numeric column. | Mean purchase amount, average salary. | | `SUM()` | Calculates the total sum of a numeric column. | Total revenue, sum of expenses. | | `COUNT()`| Counts the number of rows or non-null values. | Total transactions, user signups. | | `MAX()` | Returns the largest value in a column. | Highest price, maximum score. | | `MIN() ` | Returns the smallest value in a column. | Lowest price, minimum score. | Most aggregate functions disregard `NULL` values, with the exception of `COUNT(*)` which counts all rows regardless of `NULL` values. ## Aggregate Function Examples Consider the following tables: **Students** | rollno | name | class | | :----- | :---- | :---- | | 1 | Troy | TE | | 1 | Shree | BE | | 2 | Harry | TE | | 3 | John | TE | | 3 | Shiv ani | TE | **purchase** | item | price | customer_name | | :----------- | :---- | :------------ | | Pen | 10 | Troy | | Bag | 1000 | Troy | | Vegetables | 500 | Troy | | Shoes | 5000 | Troy | | Water Bottle | 800 | XYZ | | Mouse | 120 | ABC | | Sun Glasses | 1350 | ABC | ## `AVG` function Calculate the average purchase amount per customer. ```sql SELECT AVG(price) AS Avg_Purchase, customer_name FROM purchase GROUP BY customer_name; ``` | Avg_Purchase | customer_name | | :----------- | :------------ | | 1 627.5000 | Troy | | 800.0000 | XYZ | | 735.0000 | ABC | ## `SUM` function Calculate the total expenditure for each customer. ```sql SELECT SUM(price) AS Total_Bill, customer_name FROM purchase GROUP BY customer_name; ``` | Total_Bill | customer_name | | :--------- | :------------ | | 6510 | Troy | | 800 | XYZ | | 1470 | ABC | ## `COUNT ` function Determine the number of items purchased by each customer. ```sql SELECT COUNT(item) AS Total_Items, customer_name FROM purchase GROUP BY customer_name; ``` | Total_Items | customer _name | | :---------- | :------------ | | 4 | Troy | | 1 | XYZ | | 2 | ABC | ## `MAX` function Identify the highest single purchase value for each customer. ```sql SELECT MAX(price) AS Highest_Purchase, customer_name FROM purchase GROUP BY customer_name; ``` | Highest_Purchase | customer_name | | :--------------- | :------------ | | 5000 | Troy | | 800 | XYZ | | 1350 | ABC | ## `MIN` function Find the lowest single purchase value for each customer. ```sql SELECT MIN(price) AS Lowest_Purchase, customer_name FROM purchase GROUP BY customer_name; ``` | Lowest_Purchase | customer_name | | :-------------- | :------------ | | 10 | Troy | | 800 | XYZ | | 120 | ABC | ## Having Clause Examples These examples demonstrate using `HAVING` to filter results based on aggregate function output. ### Example 1: Filtering by Group Count Identify classes with more than 2 students. ```sql SELECT COUNT(class) AS strength, class FROM Students GROUP BY class HAVING COUNT(class) > 2; ``` This query provides the count of students per class, filtered to include only those classes where the count exceeds 2. | strength | class | | :------- | :---- | | 4 | TE | ### Example 2: Filtering by Minimum Aggregate Value Find customers whose minimum purchase price is greater than 10. ```sql SELECT customer_name, MIN(price) AS MIN_PURCHASE FROM purchase GROUP BY customer_name HAVING MIN(price) > 10; ``` This query calculates the minimum purchase for each customer and includes only those customers where this minimum is above 10. | customer_name | MIN_PURCHASE | | :------------ | :----------- | | XYZ | 800 | | ABC | 120 | ### Example 3: Filtering and Ordering by Average Aggregate Value List customers with an average purchase price greater than 550, ordered by name descending. ```sql SELECT customer_name, AVG(price) AS Average_Purchase FROM purchase GROUP BY customer_name HAVING AVG(price) > 550 ORDER BY customer_name DESC; ``` This query computes the average purchase price per customer, filters for averages above 550, and presents the results in descending order of customer name. | customer_name | Average_Purchase | | :------------ | :--------------- | | XYZ | 800.0000 | | Troy | 1627.5000 | | ABC | 735.0000 | ### Example 4: Combining WHERE and HAVING Calculate the total purchase amount for customers whose names start with "S" and whose total purchase exceeds 1000. ```sql SELECT customer_name, SUM(price) AS Total_Purchase FROM purchase WHERE customer_ name LIKE "S%" -- WHERE filters rows before grouping GROUP BY customer_name HAVING SUM(price) > 1000; -- HAVING filters groups after aggregation ``` This query first filters rows to include only customers whose names start with 'S', then groups by customer name, calculates the total purchase, and finally filters these groups to include only those with a total exceeding 1000. Combining `WHERE` and `HAVING` allows for efficient multi -stage filtering. | customer_name | Total_Purchase | | :------------ | :------------- | | Troy | 6510 |