Last Updated :
23 Dec, 2024
In SQL, the WHERE and HAVING clauses are essential for filtering data and refining query results. While both serve the purpose of applying conditions, they are used at different stages of query execution and for distinct purposes. Understanding the differences between the WHERE and HAVING clauses is important for writing optimized and effective SQL queries.
In this article, we will provide an in-depth comparison, practical examples, and clear explanations to enhance our understanding. By the end, we will be equipped to use WHERE and HAVING clauses effectively in our SQL queries.
Difference Between Where and Having Clause in SQL
Before going into examples, it’s important to understand the distinctions between the WHERE and HAVING clauses. The table below outlines their key differences for a clear comparison.
| WHERE Clause | HAVING Clause |
|---|---|
| Filters rows before groups are aggregated. | Filters groups after the aggregation process.. |
| WHERE Clause can be used without GROUP BY Clause | HAVING Clause can be used with GROUP BY Clause |
| WHERE Clause implements in row operations | HAVING Clause implements in column operation |
| WHERE Clause cannot contain aggregate function | HAVING Clause can contain aggregate function |
| WHERE Clause can be used with SELECT, UPDATE, DELETE statement. | HAVING Clause can only be used with SELECT statement. |
| WHERE Clause is used before GROUP BY Clause | HAVING Clause is used after GROUP BY Clause |
| WHERE Clause is used with single row function like UPPER, LOWER etc. | HAVING Clause is used with multiple row function like SUM, COUNT etc. |
Understanding the WHERE Clause in SQL
WHERE Clause is used to filter the records from the table or used while joining more than one table. Only those records will be extracted who are satisfying the specified condition in the WHERE clause. It can be used with SELECT, UPDATE, and DELETE statements. It is applied before any grouping or aggregation occurs in a query
Example: Using the WHERE Clause
Consider the following Student table. The table below contains details of students, including their roll numbers, names, and ages. We can use SQL queries to filter, sort, or retrieve specific data from this table based on various conditions.
Student Table
Filtering Students Aged 18 or Above
In this example, it effectively retrieves students aged 18 or older, excluding those who do not meet the criteria. This approach ensures a refined and focused result set.
Query:
SELECT S_Name, Age
FROM Student
WHERE Age >=18
Output
Students Aged 18 or Above
Explanation:
- The query selects the columns
S_NameandAgefrom theStudenttable. - The
WHEREclause filters rows where theAgeis greater than or equal to 18. - Only rows satisfying the condition are included in the result set.
HAVING Clause
HAVING Clause is used to filter the records from the groups based on the given condition in the HAVING Clause. Those groups who will satisfy the given condition will appear in the final result. It is applied after the grouping and aggregation of data.
Query:
SELECT Age, COUNT(Roll_No) AS No_of_Students
FROM Student GROUP BY Age
HAVING COUNT(Roll_No) > 1
Output
|
Age |
No_of_Students |
|---|---|
|
17 |
3 |
|
20 |
2 |
|
21 |
2 |
Conclusion
While both WHERE and HAVING clauses are used for filtering in SQL, they are applied at different stages of query execution and serve distinct purposes: The WHERE clause filters rows before any grouping or aggregation occurs. The HAVING clause filters grouped data after aggregation. Understanding these differences ensures efficient query design and accurate results. Use WHERE for conditions on individual rows and HAVING for conditions on grouped data.
I have the following two tables:
Lecturers (LectID, Fname, Lname, degree)Lecturers_Specialization (LectID, Expertise)
I want to find the lecturer with the most Specialization.
When I try this, it is not working:
SELECT
L.LectID,
Fname,
Lname
FROM Lecturers L,
Lecturers_Specialization S
WHERE L.LectID = S.LectID
AND COUNT(S.Expertise) >= ALL (SELECT
COUNT(Expertise)
FROM Lecturers_Specialization
GROUP BY LectID);
But when I try this, it works:
SELECT
L.LectID,
Fname,
Lname
FROM Lecturers L,
Lecturers_Specialization S
WHERE L.LectID = S.LectID
GROUP BY L.LectID,
Fname,
Lname
HAVING COUNT(S.Expertise) >= ALL (SELECT
COUNT(Expertise)
FROM Lecturers_Specialization
GROUP BY LectID);
What is the reason?
asked Feb 12, 2012 at 22:17
2
WHERE clause introduces a condition on individual rows; HAVING clause introduces a condition on aggregations, i.e. results of selection where a single result, such as count, average, min, max, or sum, has been produced from multiple rows. Your query calls for a second kind of condition (i.e. a condition on an aggregation) hence HAVING works correctly.
As a rule of thumb, use WHERE before GROUP BY and HAVING after GROUP BY. It is a rather primitive rule, but it is useful in more than 90% of the cases.
While you’re at it, you may want to re-write your query using ANSI version of the join:
SELECT L.LectID, Fname, Lname
FROM Lecturers L
JOIN Lecturers_Specialization S ON L.LectID=S.LectID
GROUP BY L.LectID, Fname, Lname
HAVING COUNT(S.Expertise)>=ALL
(SELECT COUNT(Expertise) FROM Lecturers_Specialization GROUP BY LectID)
This would eliminate WHERE that was used as a theta join condition.
Alexander
110k32 gold badges211 silver badges206 bronze badges
answered Feb 12, 2012 at 22:20
6
First we should know the order of execution of Clauses i.e
FROM > WHERE > GROUP BY > HAVING > DISTINCT > SELECT > ORDER BY.
Since WHERE Clause gets executed before GROUP BY Clause the records cannot be filtered by applying WHERE to a GROUP BY applied records.
«HAVING is same as the WHERE clause but is applied on grouped records».
first the WHERE clause fetches the records based on the condition then the GROUP BY clause groups them accordingly and then the HAVING clause fetches the group records based on the having condition.
answered Mar 27, 2017 at 13:28
PardhuPardhu
1,97716 silver badges17 bronze badges
2
HAVING operates on aggregates. Since COUNT is an aggregate function, you can’t use it in a WHERE clause.
Here’s some reading from MSDN on aggregate functions.
answered Feb 12, 2012 at 22:19
Daniel MannDaniel Mann
59.2k13 gold badges105 silver badges127 bronze badges
-
WHEREclause can be used withSELECT,INSERT, andUPDATEstatements, whereasHAVINGcan be used only withSELECTstatement. -
WHEREfilters rows before aggregation (GROUP BY), whereasHAVINGfilter groups after aggregations are performed. -
Aggregate function cannot be used in
WHEREclause unless it is in a subquery contained inHAVINGclause, whereas aggregate functions can be used inHAVINGclause.
Source
zhulien
5,7254 gold badges24 silver badges39 bronze badges
answered May 28, 2016 at 17:00
1
Didn’t see an example of both in one query. So this example might help.
/**
INTERNATIONAL_ORDERS - table of orders by company by location by day
companyId, country, city, total, date
**/
SELECT country, city, sum(total) totalCityOrders
FROM INTERNATIONAL_ORDERS with (nolock)
WHERE companyId = 884501253109
GROUP BY country, city
HAVING country = 'MX'
ORDER BY sum(total) DESC
This filters the table first by the companyId, then groups it (by country and city) and additionally filters it down to just city aggregations of Mexico. The companyId was not needed in the aggregation but we were able to use WHERE to filter out just the rows we wanted before using GROUP BY.
answered Jul 27, 2016 at 23:15
NhanNhan
1,4841 gold badge14 silver badges16 bronze badges
3
You can not use where clause with aggregate functions because where fetch records on the basis of condition, it goes into table record by record and then fetch record on the basis of condition we have give. So that time we can not where clause. While having clause works on the resultSet which we finally get after running a query.
Example query:
select empName, sum(Bonus)
from employees
order by empName
having sum(Bonus) > 5000;
This will store the resultSet in a temporary memory, then having clause will perform its work. So we can easily use aggregate functions here.
answered Dec 10, 2013 at 11:30
Akash5288Akash5288
1,95522 silver badges16 bronze badges
2
1.
We can use aggregate function with HAVING clause not by WHERE clause e.g. min,max,avg.
2.
WHERE clause eliminates the record tuple by tuple
HAVING clause eliminates entire group from the collection of group
Mostly HAVING is used when you have groups of data and WHERE is used when you have data in rows.
answered Jun 29, 2016 at 15:37
WHERE clause is used to eliminate the tuples in a relation,and HAVING clause is used to eliminate the groups in a relation.
HAVING clause is used for aggregate functions such as
MIN,MAX,COUNT,SUM .But always use GROUP BY clause before HAVING clause to minimize the error.
answered Jul 22, 2020 at 13:25
Doddi girishDoddi girish
1151 gold badge1 silver badge8 bronze badges
Both WHERE and HAVING are used to filter data.
In case of a WHERE statement, data filtering happens before you pull the data for operation.
SELECT name, age
FROM employees
WHERE age > 30;
Here the WHERE clause filters rows before the SELECT operation is performed.
SELECT department, avg(age) avg_age
FROM employees
GROUP BY department
HAVING avg_age> 35;
HAVING filters the data after the SELECT operation is performed. Here the operation of computing (aggregation) is done first and then a filter is applied to the result using a HAVING clause.
answered Jan 10, 2022 at 16:46
Mithun ManoharMithun Manohar
5961 gold badge7 silver badges23 bronze badges
1
Start asking to get answers
Find the answer to your question by asking.
Ask question
Explore related questions
See similar questions with these tags.
From Wikipedia, the free encyclopedia
A HAVING clause in SQL specifies that an SQL SELECT statement must only return rows where aggregate values meet the specified conditions.[1]: 125–127
HAVING and WHERE are often confused by beginners, but they serve different purposes. WHERE is taken into account at an earlier stage of a query execution, filtering the rows read from the tables. If a query contains GROUP BY, rows from the tables are grouped and aggregated. After the aggregating operation, HAVING is applied, filtering out the rows that don’t match the specified conditions. Therefore, WHERE applies to data read from tables, and HAVING should only apply to aggregated data, which isn’t known in the initial stage of a query.
To view the present condition formed by the GROUP BY clause, the HAVING clause is used.[clarification needed]
To return a list of department IDs whose total sales exceeded $1000 on the date of January 1, 2000, along with the sum of their sales on that date:
SELECT DeptID, SUM(SaleAmount) FROM Sales WHERE SaleDate = '2000-01-01' GROUP BY DeptID HAVING SUM(SaleAmount) > 1000
Referring to the sample tables in the Join example, the following query will return the list of departments which have more than 1 employee:
SELECT DepartmentName, COUNT(*) FROM Employee JOIN Department ON Employee.DepartmentID = Department.DepartmentID GROUP BY DepartmentName HAVING COUNT(*) > 1;
HAVING is convenient, but not necessary. Code equivalent to the example above, but without using HAVING, might look like:
SELECT * FROM ( SELECT DepartmentName AS deptNam, COUNT(*) AS empCount FROM Employee AS emp JOIN Department AS dept ON emp.DepartmentID = dept.DepartmentID GROUP BY deptNam ) AS grp WHERE grp.empCount > 1;
- ^ PostgreSQL 16.1 Documentation (PDF). The PostgreSQL Global Development Group. 2023. Retrieved February 8, 2024.
- The HAVING and GROUP BY SQL clauses Archived 2011-06-03 at the Wayback Machine
- SQL Aggregate Functions Archived May 3, 2017, at the Wayback Machine
Мы уже рассматривали запрос получения средней стоимости аренды жилых помещений в зависимости от
типа жилья:
SELECT home_type, AVG(price) as avg_price FROM Rooms GROUP BY home_typeДавайте доработаем этот запрос таким образом, чтобы в итоговой выборке отображались только те группы, чья средняя стоимость больше 50.
Обладая предыдущим опытом, есть большой соблазн попытаться использовать для этих целей оператор WHERE. Но при попытке выполнить такой запрос
СУБД неминуемо выдаст ошибку, указав, что мы некорректно используем синтаксис WHERE avg_price > 50.SELECT home_type, AVG(price) as avg_price FROM Rooms GROUP BY home_type WHERE avg_price > 50Говоря наперёд, для фильтрации групп мы должны использовать оператор HAVING:
SELECT home_type, AVG(price) as avg_price FROM Rooms GROUP BY home_type HAVING avg_price > 50Порядок выполнения SQL запроса
Но почему же мы не могли использовать WHERE, и зачем нужен отдельный оператор для этой цели? Все дело в порядке выполнения SQL запроса.
![]()
Наш первый запрос был неверный, потому что мы пытались использовать поле avg_price у образовавшихся групп ещё до их образования,
так как выполнение оператора WHERE предшествует группировке.То есть оператор WHERE в момент его исполнения ничего не знает о последующей группировке, он работает только с записями из таблицы.
Так мы, например, с его помощью можем отфильтровать записи таблицы Rooms по цене до применения группировки и лишь затем вычислить среднюю стоимость
групп оставшегося жилья:SELECT home_type, AVG(price) as avg_price FROM Rooms WHERE price > 50 GROUP BY home_typeОбщая структура запроса с оператором HAVING
SELECT [константы, агрегатные_функции, поля_группировки] FROM имя_таблицы WHERE условия_на_ограничения_строк GROUP BY поля_группировки HAVING условие_на_ограничение_строк_после_группировки ORDER BY условие_сортировкиПример использования HAVING
Для примера давайте получим минимальную стоимость каждого типа жилья c телевизором. При этом нас интересуют только типы жилья, содержащие как минимум 5 жилых
помещений, относящихся к ним.Чтобы получить такой результат, мы должны:
-
Сначала получить все данные из таблицы
-
Затем выбрать из всех записей таблицы Room только интересующие нас, т.е. только жильё с телевизором
SELECT ... FROM Rooms WHERE has_tv = True -
Затем сгруппировать данные записи о жилых помещениях по их типу
SELECT ... FROM Rooms WHERE has_tv = True GROUP BY home_type -
После этого отфильтровать полученные группы по условию. Нас интересуют группы, имеющие как минимум 5 представителей
SELECT ... FROM Rooms WHERE has_tv = True GROUP BY home_type HAVING COUNT(*) >= 5 -
И под конец посмотреть, что нас просят в задании и, соответственно, добавить вывод необходимой информации. В нашем случае, нам
необходимо вывести название типа жилья и его минимальную стоимость.SELECT home_type, MIN(price) as min_price FROM Rooms WHERE has_tv = True GROUP BY home_type HAVING COUNT(*) >= 5;
In addition to creating groups using GROUP BY clause, you can also decide which groups to include in the output and which to exclude. For example, you might want a list of jobs for which more than one employee is hired. To get this kind of data you have to filter by group and not by individual rows.
SQL provides a clause for this purpose: the HAVING clause.
Just as WHERE is to SELECT, so is HAVING to GROUP BY. In other words, the WHERE clause filters individual rows, and the HAVING clause filters the groups created by the GROUP BY clause. So when you use the HAVING clause, you effectively include or exclude whole groups of data from the query results.
Syntax
The syntax of HAVING is similar to WHERE; just the keyword is different. And of course HAVING is used only in conjunction with the GROUP BY clause.
SELECT column_name(s)
FROM table_name
WHERE condition
GROUP BY column_name(s)
HAVING condition;
Sample Table
To help you better understand the examples, and enable you to follow along with the tutorial, we are going to use the following sample table.
This table is part of an ‘Employee Management System’ that contains basic information about employees.
| ID | Name | City | Job | Salary | HireDate |
| 1 | Bob | New York | Manager | 60000 | 2012-03-07 |
| 2 | Kim | Chicago | Manager | 55000 | 2014-04-25 |
| 3 | Eve | New York | Developer | 32000 | 2015-03-11 |
| 4 | Max | New York | Janitor | 9000 | 2015-01-15 |
| 5 | Joe | Chicago | Developer | 30000 | 2016-10-05 |
| 6 | Amy | New York | Developer | 31000 | 2013-05-13 |
| 7 | Ray | New York | Supervisor | 40000 | 2016-01-15 |
| 8 | Sam | Chicago | Janitor | 10000 | 2012-02-10 |
| 9 | Liv | Chicago | Developer | 30000 | 2014-08-10 |
| 10 | Ian | New York | Janitor | 8500 | 2018-01-12 |
Using HAVING Clause
After the data is grouped, you may want to apply a filter condition to include or exclude certain groups. The HAVING clause is where you should place these types of filter conditions.
For example, the following query returns a list of jobs for which more than one employee is hired.
SELECT Job, COUNT(*) AS emp_count
FROM Employees
GROUP BY Job
HAVING COUNT(*) > 1;
| Job | emp_count |
| Developer | 4 |
| Janitor | 3 |
| Manager | 2 |
The first three lines of this query instructs the DBMS to group the data by ‘Job’ and then count the number of employees for each group. The final line adds a HAVING clause that filters out those groups and excludes jobs with only one or no employee.
Difference Between HAVING and WHERE
HAVING is very similar to WHERE. In fact, all the options and techniques you’ve learned so far about WHERE (including wildcards and multiple operators) can also be applied to HAVING.
The only difference is that WHERE filters rows and HAVING filters groups. This is because, WHERE acts on data before it is grouped, and HAVING acts on data after the groups have been created.
To demonstrate, let’s modify the above example to put the grouping condition in the WHERE clause instead of HAVING:
SELECT Job, COUNT(*) AS emp_count
FROM Employees
WHERE COUNT(*) > 1
GROUP BY Job;
--An aggregate may not appear in the WHERE clause unless it is
in a subquery contained in a HAVING clause or a select list,
and the column being aggregated is an outer reference.
This query fails because the condition in the WHERE clause is evaluated before the grouping occurs. In fact, WHERE has no idea what a group is, so it can’t perform any functions on groups.
Before adding a condition to a query with a GROUP BY clause, think carefully whether the condition works on raw data, in which case it belongs to the WHERE clause; and if it works on grouped data, it belongs to the HAVING clause.
Using HAVING and WHERE in One Statement
You might be wondering if there is a need to use both WHERE and HAVING clauses in one statement? Actually, yes, there is.
Suppose you want to further filter the above query so that it takes into account all the job titles except ‘Janitor’. To do this, you can add a WHERE clause that filters all job titles except ‘Janitor’. You can then add a HAVING clause to filter groups with only two or more employees.
SELECT Job, COUNT(*) AS emp_count
FROM Employees
WHERE Job != 'Janitor'
GROUP BY Job
HAVING COUNT(*) > 1;
| Job | emp_count |
| Developer | 4 |
| Manager | 2 |
Filter Groups by Aggregate Functions that don’t Appear in SELECT
You may use aggregate functions in the HAVING clause, that do not appear in the SELECT clause, as demonstrated by the following query.
SELECT Job, COUNT(*) AS emp_count
FROM Employees
GROUP BY Job
HAVING AVG(Salary) > 30500;
| Job | emp_count |
| Developer | 4 |
| Manager | 2 |
| Supervisor | 1 |
This query groups the data by the ‘Job’ column and then counts the number of employees for each group, but then the filter condition in the HAVING clause excludes all groups for which the average salary is less than $30,500.
