DBMSCSL303 / MAL505
Module 2: Core SQL

Lecture 07: Aggregation & Grouping

Aggregate Functions, NULL Semantics, GROUP BY Rules, and HAVING vs WHERE

Lecture Source Slide Deck

Original Slides: Lecture 07 (38 slides) · Amit Kumar Dhar (IIT Bhilai)
Download lecture07.pdf

1. Aggregate Functions

Aggregate functions take a collection of values across multiple rows and condense them into a single scalar summary value:

FunctionDescriptionNULL Handling
COUNT(*)Counts total number of rows returned.Includes rows with NULLs.
COUNT(column)Counts rows where column is not null.Ignores NULLs.
COUNT(DISTINCT col)Counts distinct non-null values.Ignores NULLs.
SUM(column)Calculates total sum of numeric values.Ignores NULLs (returns NULL if all rows are null).
AVG(column)Arithmetic mean (sumcount of non-nulls).Ignores NULLs.
MIN(column) / MAX(column)Smallest / largest value.Ignores NULLs.

The Golden Rule of NULLs in Aggregation

AVG(salary) divides the sum only by rows where salary IS NOT NULL. It does not treat NULL as zero. If you want NULL treated as zero, you must write AVG(COALESCE(salary, 0)).


2. GROUP BY: Partitioning Rows into Buckets

The GROUP BY clause divides table rows into distinct subsets sharing common attribute values, evaluating aggregate functions independently for each subset.

SELECT 
    dept_name,
    COUNT(*) AS total_faculty,
    ROUND(AVG(salary), 2) AS average_salary,
    MAX(salary) AS highest_salary
FROM instructor
GROUP BY dept_name;

The Cardinal Rule of GROUP BY

Any column appearing in the SELECT list must either be specified directly in the GROUP BY clause, or be enclosed inside an aggregate function.

-- WRONG in ANSI SQL: 'name' is not in GROUP BY and not aggregated!
SELECT dept_name, name, AVG(salary)
FROM instructor
GROUP BY dept_name;

-- CORRECT:
SELECT dept_name, AVG(salary)
FROM instructor
GROUP BY dept_name;

3. HAVING vs. WHERE

A common mistake is attempting to filter aggregated values inside a WHERE clause.

Execution Pipeline:
1. FROM               Identify tables & joins
2. WHERE              Filter individual rows BEFORE grouping
3. GROUP BY           Group rows into buckets
4. HAVING             Filter grouped buckets based on aggregate results
5. SELECT             Project columns & evaluate aggregates
6. ORDER BY           Sort final result rows
-- Find departments with more than 2 instructors whose average salary exceeds 70,000
SELECT 
    dept_name,
    COUNT(*) AS num_instructors,
    AVG(salary) AS avg_sal
FROM instructor
WHERE salary > 50000        -- Filter individual instructors FIRST
GROUP BY dept_name          -- Group by department
HAVING COUNT(*) > 2         -- Filter groups AFTER aggregation
   AND AVG(salary) > 70000;

4. Topic Practice Questions

On this page