Friday, March 27, 2026

Oracle SQL GROUP BY and HAVING

Oracle SQL GROUP BY and HAVING: Complete Guide

Oracle SQL GROUP BY and HAVING: Complete Guide

The GROUP BY clause lets you summarize data by grouping rows that share the same values in specified columns. The HAVING clause lets you filter those groups based on aggregate results. Together they are essential for creating meaningful summaries and reports from your data.

Learning Objectives
By the end of this guide you will understand how GROUP BY works, know exactly what can and cannot appear in the SELECT list, master the difference between WHERE and HAVING, and learn how to use aggregate functions correctly.

1. How GROUP BY Works

GROUP BY collapses multiple rows that share the same value in the grouping column(s) into a single summary row. Aggregate functions are then applied to each group.

-- Without GROUP BY: one result for the entire table
SELECT COUNT(*), AVG(salary)
FROM   employees;

-- With GROUP BY: one result row per department
SELECT department_id, COUNT(*), AVG(salary)
FROM   employees
GROUP BY department_id;

2. The SELECT List Rule

When using GROUP BY, every column in the SELECT list must be either:

  • Included in the GROUP BY clause, or
  • Wrapped inside an aggregate function
-- Correct
SELECT department_id, COUNT(*), AVG(salary)
FROM   employees
GROUP BY department_id;

-- Incorrect — last_name is neither grouped nor aggregated
SELECT department_id, last_name, COUNT(*)
FROM   employees
GROUP BY department_id;
Common mistake: You can GROUP BY a column without selecting it, but you cannot select a non-aggregated column without including it in the GROUP BY clause.

3. Grouping on Multiple Columns

You can group by more than one column. Each unique combination of values creates a separate group.

SELECT department_id, job_id, COUNT(*) AS headcount, SUM(salary) AS total_salary
FROM   employees
GROUP BY department_id, job_id
ORDER BY department_id, job_id;

4. WHERE vs HAVING

WHEREHAVING
FiltersIndividual rowsGroups after grouping
RunsBefore GROUP BYAfter GROUP BY
Aggregate functions allowed?NoYes
-- WHERE filters rows before grouping
SELECT department_id, COUNT(*), AVG(salary)
FROM   employees
WHERE  salary > 5000
GROUP BY department_id;

-- HAVING filters groups after grouping
SELECT department_id, COUNT(*), AVG(salary)
FROM   employees
GROUP BY department_id
HAVING AVG(salary) > 8000;

5. Aggregate Functions

FunctionNULL handlingEmpty group result
COUNT(*)Counts all rows0
COUNT(col)Skips NULLs0
SUM(col), AVG(col), MAX(col), MIN(col)Skips NULLsNULL

6. Interactive Practice Quiz

Q1. Which query will raise an error?

Q2. You want to show only departments where the average salary is greater than 8000. Which clause should you use?

Q3. What does this query return?
SELECT MAX(AVG(salary)) FROM employees GROUP BY department_id;

Conclusion

GROUP BY and HAVING are powerful tools for summarizing and filtering grouped data. The most important rules to remember are: every non-aggregated column in the SELECT list must appear in the GROUP BY clause, WHERE filters rows before grouping, and HAVING filters groups after grouping.

Practice writing queries that combine grouping, aggregates, and both WHERE and HAVING clauses — these patterns appear frequently in real-world reporting and analysis.

No comments:

Post a Comment

Non-Equijoins and Self-Joins in Oracle SQL

Non-Equijoins and Self-Joins in Oracle SQL Non-Equijoins and Self-Joins in Oracle SQL: Complete Guide Most joins in SQL use the e...