SQL HAVING Clause
1. Introduction
A SQL HAVING clause is a part of a SQL SELECT statement that filters out the rows that don’t match the aggregating conditions. Here is the syntax for the HAVING clause in a SELECT statement:
HAVING Syntax
SELECT select_list [ INTO new_table ] [ FROM table_source ] [ GROUP BY group_by_expression ] [ HAVING search_condition ] [ ORDER BY columns ]
Note: the Having clause is right after a Group By clause if it exists and before an Order By clause. The search_condition after HAVING must return a boolean value.
In this example, I will demonstrate the SQL HAVING clause:
- with aggregate functions: count, avg, sum, min, and max.
- with a GROUP BY clause.
- without a GROUP BY clause.
- with more than one aggregate functions.
- with an ORDER BY clause.
2. Technologies Used
The example code in this article was built and run using:
- SQL
- MS SQL Server
- SQuirrel Client 3.9.0
3. Setup Data
In this step, I will create two database tables:
- categories – has two columns: category_id and category_name. It has three records.
- products – has five columns: product_id, category_id, product_name, price, and release_date. It has eight records.
setupdata.sql
create table categories ( category_id INT, category_name VARCHAR(40) ); create table products ( product_id INT, category_id INT, product_name VARCHAR(40), price DECIMAL(5,2) , release_date DATE ); insert into categories ( category_id , category_name ) values(1, 'Mobile'); insert into categories ( category_id , category_name ) values(2, 'Headphone'); insert into categories ( category_id , category_name ) values(3, 'Tablet'); insert into products ( product_id , category_id , product_name, price, release_date ) values(1027,2, 'Headphone 700',87.99, '5/13/2019'); insert into products ( product_id , category_id , product_name, price, release_date ) values(1028,2, 'Headphone 450BT', 97.99, '2/4/2020'); insert into products ( product_id , category_id , product_name, price, release_date ) values(1029,2, 'HD 1000XM3', 107.99, '8/5/2018'); insert into products ( product_id , category_id , product_name, price, release_date ) values(1030,2, 'HD SoundES18',117.99, '1/1/2017'); insert into products ( product_id , category_id , product_name, price, release_date ) values(1021,1, 'APPLE 700',400.99, '9/20/2019'); insert into products ( product_id , category_id , product_name, price, release_date ) values(1022,1, 'Samsung 5',357.99, '8/23/2019'); insert into products ( product_id , category_id , product_name, price, release_date ) values(1035,3, 'GalatS6',187.99, '10/13/2019'); insert into products ( product_id , category_id , product_name, price, release_date ) values(1036,3, 'MS', 250.99, '6/13/2017');
Verify the data with a Select statement
SELECT category_id,
count(*) totalProductCount
FROM products
GROUP BY category_id Query Results
| category_id | totalProductCount |
| 1 | 2 |
| 2 | 4 |
| 3 | 2 |
As the results show, only the category_id = 2 has more than 2 products.
4. SQL Having Clause
4.1 HAVING Clause Without Group By
In this step, I will use a HAVING clause to find the minimum and maximum prices from the products table when the minimum and maximum prices are different.
HAVING min(price) != Max(price)
SELECT Min(price) min,
Max(price) max
FROM products
HAVING Min(price) != Max(price); Query Results
| min | max |
| 87.99 | 400.99 |
Note: when a HAVING clause is used without a GROUP BY clause, then the aggregate function is applied to the entire table. In this case, it returns 1 row.
The next query returns no data.
HAVING Min(price) = Max(price)
SELECT Min(price) min,
Max(price) max
FROM products
HAVING Min(price) = Max(price); No data was returned
| min | max |
4.2 GROUP BY Category HAVING Count Greater Than 2
In this step, I will use a HAVING clause with a GROUP BY clause to list the minimum and maximum prices for each category.
HAVING after GROUP BY
SELECT category_id,
Min(price) min,
Max(price) max
FROM products
GROUP BY category_id
HAVING Min(price) != Max(price); Query Results
| category_id | min | max |
| 1 | 357.99 | 400.99 |
| 2 | 87.99 | 117.99 |
| 3 | 187.99 | 250.99 |
The next query uses a HAVING clause with a GROUP BY clause which filters the categories with less than 2 products.
HAVING count(*> 2
SELECT category_id,
Sum(price) totalProductPrice
FROM products
GROUP BY category_id
HAVING Count(*) >2;Query Results
| category_id | totalProductPrice |
| 2 | 411.96 |
4.3 Group By Category Having Sum Greater Than 300
In this step, I will demonstrate two ways to use a HAVING clause with a joined table.
HAVING Sum(price) > 300
SELECT c.category_id,
c.category_name ,
Sum(price) totalProductPrice
FROM products p,
categories c
WHERE p.category_id = c.category_id
GROUP BY c.category_id,
c.category_name
HAVING Sum(price) >300;Query Results
| category_id | category_name | totalProductPrice |
| 1 | Mobile | 758.98 |
| 2 | Headphone | 411.96 |
| 3 | Tablet | 438.98 |
In th next query, the joined clause is applied to the filtered query results.
Having in a subQuery
SELECT *
FROM categories c,
(SELECT category_id,
Sum(price) totalProductPrice
FROM products
GROUP BY category_id
HAVING Count(*) > 2) filterdV
WHERE c.category_id = filterdV.category_id; Query Results
| category_id | category_name | category_id | totalProductPrice |
| 2 | Headphone | 2 | 411.96 |
4.4 Group by Category HAVING Sum between 300 and 500
In this step, I will show two queries with more than one condition used in the HAVING clause.
HAVING with 2 Conditions
SELECT c.category_id,
c.category_name ,
Sum(price) totalProductPrice
FROM products p,
categories c
WHERE p.category_id = c.category_id
GROUP BY c.category_id,
c.category_name
HAVING Sum(price) >300 and sum(price) < 500;Query Results
| category_id | category_name | totalProductPrice |
| 2 | Headphone | 411.96 |
| 3 | Tablet | 438.98 |
The next query shows categories with more than 2 products and a total price of more than 300.
HAVING with 2 Conditions -2
SELECT c.category_id,
c.category_name ,
Sum(price) totalProductPrice
FROM products p,
categories c
WHERE p.category_id = c.category_id
GROUP BY c.category_id,
c.category_name
HAVING Sum(price) >300 and count(*) > 2Query Results
| category_id | category_name | totalProductPrice |
| 2 | Headphone | 411.96 |
4.5 Having Avg and Order By Avg
In this step, I will show how to find the categories whose average product price is more than 100, and the query results are ordered by the average product price.
Having Average With Order By
SELECT c.category_id,
c.category_name ,
avg(price) avgPrice
FROM products p,
categories c
WHERE p.category_id = c.category_id
GROUP BY c.category_id,
c.category_name
HAVING avg(price) > 100
order by avg(price);Query Results
| category_id | category_name | avgPrice |
| 2 | Headphone | 102.99 |
| 3 | Tablet | 219.49 |
| 1 | Mobile | 379.49 |
5. Summary
The HAVING clause is used in a SELECT statement which specifies conditions to filter which group results appear in the results. The conditions are the Boolean type which can be used with logical operators: AND and OR. In this example, I demonstrated the following usages of a Having clause:
- Having min(price) ! = max(price) clause without a Group by clause.
- Group by category and filtering with Having count(product) > 2.
- Group by category and filter with Having sum(price) > 300.
- Group by category and filter with Having avg(price) > 100, then Order By avg(price).
6. Download the Source Code
You can download the full source code of this example here: SQL HAVING Clause

