HAVING
The HAVING clause specifies a search condition using an aggregate function. It filters the records returned from a GROUP BY clause that do not fulfill the specified condition.
Differences between WHERE and HAVING
| WHERE | HAVING |
|---|---|
The |
The |
The |
The |
The |
The |
Syntax
SELECT column_1, column_2,...
FROM table_name
GROUP BY column_name(s)
HAVING condition_aggregate_function
This syntax includes the following elements:
-
SELECT column_1, column_2,…selects the columns to display. -
FROM table_nameselects the table to retrieve data from. -
GROUP BY column_name(s)lists the columns to group. -
HAVING condition_aggregate_functionprovides the condition for filtering rows formed by theGROUP BYclause. The condition can use an aggregate function such assum(),count(), ormin().
Examples
Assume there are two tables: student and score.
Create the student table:
CREATE TABLE student (
stud_id int,
stud_name text
);
INSERT INTO student
(stud_id, stud_name)
VALUES
(992831192, 'Mary'),
(992811191, 'Bobby'),
(992311195, 'Sean'),
(998311193, 'Harry'),
(998311194, 'William'),
(928311197, 'Kate'),
(928311190, 'Tom'),
(928311199, 'Sully'),
(998311196, 'Susan');
SELECT * FROM student;
This returns:
+------------+------------+
| stud_id | stud_name |
+------------+------------+
| 992831192 | Mary |
| 992811191 | Bobby |
| 992311195 | Sean |
| 998311193 | Harry |
| 998311194 | William |
| 928311197 | Kate |
| 928311190 | Tom |
| 928311199 | Sully |
| 998311196 | Susan |
+------------+------------+
Create the score table:
CREATE TABLE score (
score_id int,
subject text,
score_val int,
stud_id int,
score_stat text
);
INSERT INTO score
(score_id, subject, score_val, stud_id, score_stat)
VALUES
(12221, 'Math', 90, 992811191, 'PASSED'),
(12222, 'Biology', 90, 992811191, 'PASSED'),
(12223, 'Art', 80, 992831192, 'PASSED'),
(12224, 'History', 70, 928311197, 'FAILED'),
(12225, 'Physics', 75, 928311190, 'FAILED'),
(12226, 'Art', 85, 928311197, 'PASSED'),
(12227, 'Biology', 90, 998311196, 'PASSED'),
(12228, 'Biology', 70, 928311199, 'FAILED'),
(12229, 'Physics', 80, 998311194, 'PASSED'),
(12231, 'Math', 80, 998311193, 'PASSED'),
(12232, 'History', 90, 992811191, 'PASSED'),
(12233, 'Math', 70, 998311194, 'FAILED'),
(12234, 'Math', 80, 928311190, 'PASSED');
SELECT * FROM score;
This returns:
+-----------+----------+------------+------------+-------------+
| score_id | subject | score_val | stud_id | score_stat |
+-----------+----------+------------+------------+-------------+
| 12221 | Math | 90 | 992811191 | PASSED |
| 12222 | Biology | 90 | 992811191 | PASSED |
| 12223 | Art | 80 | 992831192 | PASSED |
| 12224 | History | 70 | 928311197 | FAILED |
| 12225 | Physics | 75 | 928311190 | FAILED |
| 12226 | Art | 85 | 928311197 | PASSED |
| 12227 | Biology | 90 | 998311196 | PASSED |
| 12228 | Biology | 70 | 928311199 | FAILED |
| 12229 | Physics | 80 | 998311194 | PASSED |
| 12231 | Math | 80 | 998311193 | PASSED |
| 12232 | History | 90 | 992811191 | PASSED |
| 12233 | Math | 70 | 998311194 | FAILED |
| 12234 | Math | 80 | 928311190 | PASSED |
+-----------+----------+------------+------------+-------------+
HAVING clause with AVG function
The following example uses the avg aggregate function to filter subjects with an average score greater than 80:
SELECT subject
FROM score
GROUP BY subject
HAVING AVG (score_val) > 80;
The query returns:
+-----------+
| subject |
+-----------+
| Art |
| Biology |
+-----------+
HAVING clause with COUNT function
The following query lists subjects that have more than two PASSED scores:
SELECT SUM(CASE WHEN score_stat = 'PASSED' THEN 1 ELSE 0 END) AS passed_count, subject
FROM score
GROUP BY subject
HAVING SUM(CASE WHEN score_stat = 'PASSED' THEN 1 ELSE 0 END) > 2;
The query returns Math as the only subject with more than two PASSED values:
+--------------+---------+
| passed_count | subject |
+--------------+---------+
| 3 | Math |
+--------------+---------+
HAVING clause with MAX function
Assume the minimum score criterion is 75. The following query finds the maximum score for each subject where the maximum is greater than 75:
SELECT subject, MAX(score_val)
FROM score
GROUP BY subject
HAVING MAX(score_val)>75;
The query returns:
+-----------+--------+
| subject | max |
+-----------+--------+
| Math | 90 |
| History | 90 |
| Physics | 80 |
| Art | 85 |
| Biology | 90 |
+-----------+--------+
HAVING with JOIN condition
To find students who have failed in their subjects, combine the student and score tables using JOIN and apply a condition on the score_stat column:
SELECT stud_name, subject, score_val, score_stat
FROM student A
JOIN score C ON A.stud_id = C.stud_id
GROUP BY stud_name, subject, score_val, score_stat
HAVING score_stat = 'FAILED';
-
The
JOINclause combines the two tables. -
The
GROUP BYclause filters records from both tables based on the specified columns. -
The
HAVINGclause filters the records returned from theGROUP BYclause according to the specified condition.
The query returns:
+------------+------------+------------+--------------+
| stud_name | subject | score_val | score_stat |
+------------+------------+------------+--------------+
| Kate | History | 70 | FAILED |
| Sully | Biology | 70 | FAILED |
| Tom | Physics | 75 | FAILED |
| William | Math | 70 | FAILED |
+------------+------------+------------+--------------+