Skillversitas

HAVING Clause

The HAVING Function

The HAVING clause is used to filter grouped results (GROUP BY) based on specific conditions. Without HAVING, we can only filter individual rows with WHERE.

WHERE vs HAVING

Aspect WHERE HAVING
When executed Before grouping After grouping
Aggregate functions Cannot be used Can be used
Example WHERE SALARY > 5000000 HAVING COUNT(*) > 3

Basic Syntax

SELECT column, aggregate_function(column)
FROM table_name
GROUP BY column
HAVING kondisi;

Execution Order

FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
  1. WHERE filters rows before grouping
  2. GROUP BY groups the remaining rows
  3. HAVING filters groups based on aggregate conditions

Example: Departments with More Than 3 Employees

SELECT DEPARTMENT, COUNT(*) AS TOTAL
FROM EMPLOYEE
GROUP BY DEPARTMENT
HAVING COUNT(*) > 3;

Example: Average Salary > 5,000,000

SELECT DEPARTMENT, AVG(SALARY) AS AVG_SALARY
FROM EMPLOYEE
GROUP BY DEPARTMENT
HAVING AVG(SALARY) > 5000000;

Example: Total Salary per Department

SELECT DEPARTMENT, SUM(SALARY) AS TOTAL_SALARY
FROM EMPLOYEE
GROUP BY DEPARTMENT
HAVING SUM(SALARY) > 20000000;

Combining WHERE and HAVING

-- Filter active employees first, then find departments with more than 3 active employees
SELECT DEPARTMENT, COUNT(*) AS TOTAL_ACTIVE
FROM EMPLOYEE
WHERE STATUS = 'Active'
GROUP BY DEPARTMENT
HAVING COUNT(*) > 3;

Combining with JOIN

SELECT D.DEPARTMENT_NAME, COUNT(*) AS TOTAL, AVG(K.SALARY) AS AVG_SALARY
FROM EMPLOYEE K
INNER JOIN DEPARTMENT D ON K.ID_DEPT = D.ID_DEPT
WHERE K.STATUS = 'Active'
GROUP BY D.DEPARTMENT_NAME
HAVING AVG(K.SALARY) > 5000000
ORDER BY AVG_SALARY DESC;

HAVING with Multiple Conditions

SELECT DEPARTMENT, COUNT(*) AS TOTAL, AVG(SALARY) AS AVG_SALARY
FROM EMPLOYEE
GROUP BY DEPARTMENT
HAVING COUNT(*) > 2
   AND AVG(SALARY) > 5000000;

Complete Analysis Example

The EMPLOYEE table:

ID NAME DEPARTMENT SALARY STATUS
1 Mike IT 7000000 Active
2 John HR 4500000 Active
3 Anna IT 5500000 Active
4 Dana HR 6000000 Active
5 Eric IT 8000000 Active
6 Frank HR 4000000 Inactive
7 Grace IT 6500000 Active
-- Departments with more than 2 active employees and an average salary above 5 million
SELECT DEPARTMENT,
       COUNT(*) AS ACTIVE_EMPLOYEES,
       ROUND(AVG(SALARY), 0) AS AVG_SALARY
FROM EMPLOYEE
WHERE STATUS = 'Active'
GROUP BY DEPARTMENT
HAVING COUNT(*) > 2
   AND AVG(SALARY) > 5000000;

Result:

DEPARTMENT ACTIVE_EMPLOYEES AVG_SALARY
IT 4 6750000

HR does not appear because its average salary is below 5 million (after filtering out inactive employees).

Common Mistakes

-- ERROR: WHERE cannot use aggregate functions
SELECT DEPARTMENT, COUNT(*)
FROM EMPLOYEE
WHERE COUNT(*) > 3  -- Wrong!
GROUP BY DEPARTMENT;

-- Correct: use HAVING
SELECT DEPARTMENT, COUNT(*)
FROM EMPLOYEE
GROUP BY DEPARTMENT
HAVING COUNT(*) > 3;

Summary

  • WHERE filters individual rows before grouping
  • HAVING filters groups after grouping
  • HAVING can use aggregate functions (COUNT, AVG, SUM, etc.)
  • Combine WHERE and HAVING for flexible data analysis

By mastering HAVING, we have completed the foundation of SQL queries. Combine all the techniques — SELECT, WHERE, JOIN, GROUP BY, and HAVING — for powerful data analysis.