When working with large datasets, it is often more useful to analyze data in groups rather than viewing individual records. SQL provides the GROUP BY clause to group rows that share common values and apply aggregate functions such as COUNT, SUM, AVG, MIN, and MAX to each group. Grouping is a core concept in SQL reporting, analytics, and business intelligence.
The GROUP BY clause is used to group rows based on one or more columns. After grouping, aggregate functions operate on each group separately and return one summary row per group.
SELECT
department,
COUNT(*) AS employee_count
FROM employees
GROUP BY department;
employees table is grouped by the department column.COUNT(*) counts how many employees exist in each department.👉 Every column in the SELECT list must either:
Incorrect example:
SELECT department, salary
FROM employees
GROUP BY department; -- ❌ ERROR
Correct example:
SELECT department, AVG(salary)
FROM employees
GROUP BY department;
GROUP BY can use more than one column. In such cases, SQL creates groups based on unique combinations of the specified columns.
SELECT
department,
job_title,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department, job_title;
The HAVING clause is used to filter groups, not individual rows. It is always used after GROUP BY and works with aggregate functions.
SELECT
department,
COUNT(*) AS employee_count
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;
Although WHERE and HAVING both filter data, they operate at different stages of query execution.
SELECT
department,
AVG(salary) AS avg_salary
FROM employees
WHERE hire_date > '2019-01-01'
GROUP BY department
HAVING AVG(salary) > 55000;
| Feature | WHERE | HAVING |
|---|---|---|
| Filters | Rows | Groups |
| Used with | Individual columns | Aggregate functions |
| Execution time | Before GROUP BY | After GROUP BY |
| Can use aggregates | ❌ No | ✔ Yes |
SQL does not execute queries in the order written.
Actual execution order:
Understanding this helps avoid logical mistakes.
You can sort grouped results using ORDER BY.
Example:
SELECT department, COUNT(*) AS emp_count
FROM employees
GROUP BY department
ORDER BY emp_count DESC;