CS Atlas GATE 2027
DBMS course
0 / 119 complete

DBMS/Phase 3 · Query Languages

Lesson 3.3.5 · Item 51 of 119

Aggregates, GROUP BY, HAVING; COUNT(*) vs COUNT(col); NULL handling

Read at your own pace. Try the questions before opening the answers.

On this page

0 · Recall Warm-up

Answer from memory first. Answers are in the Answer Vault at the bottom.

  1. What is TRUE AND UNKNOWN, and FALSE AND UNKNOWN? from Lesson 3.3.4
  2. Does SQL keep duplicate rows in results? from Lesson 3.3.3
  3. What does γ do in extended RA? from Lesson 3.1.6

1 · The Hook

"How many students are there?" "Average CGPA per department?" "Departments with more than one student?" These need aggregates. Two NULL rules create the classic GATE question: COUNT(*) and COUNT(cgpa) give different answers, and AVG(cgpa) is not SUM(cgpa) / COUNT(*).

2 · Predict First

With Esha's NULL CGPA, what are COUNT(*), COUNT(cgpa) and AVG(cgpa) over STUDENT?

Make a guess in your head. The answer opens Section 3.

3 · Core Concept

Predict First — the answer

COUNT(*) = 5 (rows). COUNT(cgpa) = 4 (non-NULL values). AVG(cgpa) = (9.1 + 7.8 + 8.4 + 6.9) / 4 = 32.2 / 4 = 8.05: NULL is ignored, so it divides by 4, not 5.

Aggregate functions

FunctionReturnsNULLs
COUNT(*)number of rowscounted (it counts rows)
COUNT(col)number of non-NULL valuesignored
COUNT(DISTINCT col)number of distinct non-NULL valuesignored
SUM(col), AVG(col)sum / average of non-NULL valuesignored
MIN(col), MAX(col)smallest / largest non-NULL valueignored

So AVG(col) = SUM(col) / COUNT(col), not SUM(col) / COUNT(*). SUM(DISTINCT col) and AVG(DISTINCT col) use each value once.

Empty input: COUNT returns 0; SUM, AVG, MIN, MAX return NULL.

GROUP BY

GROUP BY dept splits the rows into groups with equal dept; each group produces one output row.

SELECT dept, COUNT(*) AS n, AVG(cgpa) AS avg_cgpa
FROM STUDENT
GROUP BY dept;
deptnavg_cgpa
CS38.75
EE17.8
ME16.9

CS has 3 rows but AVG uses Asha and Chirag only: (9.1 + 8.4) / 2 = 8.75.

SELECT-list rule: with GROUP BY, the SELECT list may contain only grouping columns and aggregates. SELECT name, dept, COUNT(*) … GROUP BY dept is an error: which name would a group of three show?

NULLs in a grouping column form one group of their own.

HAVING

HAVING filters groups after grouping (WHERE filters rows before):

SELECT dept, COUNT(*) FROM STUDENT
WHERE cgpa > 7          -- rows: Asha, Bhavin, Chirag
GROUP BY dept
HAVING COUNT(*) >= 2;   -- groups: CS (2)

Result: (CS, 2). Esha is removed by WHERE (UNKNOWN), Diya too (6.9).

Full evaluation order

FROM → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY.

  • Aggregates cannot appear in WHERE (groups do not exist yet): WHERE COUNT(*) > 1 is an error.
  • HAVING without GROUP BY treats the whole table as one group.
  • An aggregate with no GROUP BY returns exactly one row.

4 · Visual

FROM STUDENT -> WHERE cgpa > 7 -> GROUP BY dept -> HAVING COUNT(*) >= 2 -> SELECT

 5 rows         3 rows             CS: Asha, Chirag    CS (2) kept          (CS, 2)
                (Esha: UNKNOWN,    EE: Bhavin          EE (1) dropped
                 Diya: 6.9 fail)

5 · Worked Examples

Example 1 Easy

Compute over ENROLL: COUNT(*), COUNT(DISTINCT roll), COUNT(DISTINCT cid).

Solution

7, 4, 4. (Esha has no enrolments.)

Example 2 Medium

SELECT cid, COUNT(*) FROM ENROLL GROUP BY cid HAVING COUNT(*) > 1;

Solution

C1: 2, C2: 2, C3: 2, C4: 1. Result: (C1, 2), (C2, 2), (C3, 2).

Example 3 GATE

What does SELECT SUM(cgpa) / COUNT(*), AVG(cgpa) FROM STUDENT; return?

Solution

SUM = 32.2. 32.2 / 5 = 6.44 (treats Esha as 0), while AVG = 32.2 / 4 = 8.05. The two differ exactly because of the NULL.

6 · GATE Traps

  • COUNT(*) counts rows; COUNT(col) skips NULLs.
  • AVG divides by the non-NULL count.
  • Aggregates over an empty set: COUNT = 0, others NULL.
  • WHERE filters rows before grouping; HAVING filters groups after; aggregates are not allowed in WHERE.
  • Non-grouped columns in SELECT with GROUP BY are an error.
  • GROUP BY puts all NULLs in one group.

7 · Memory Hook

"Star counts seats, column counts people sitting." COUNT(*) counts chairs (rows); COUNT(cgpa) counts chairs with someone in them. And "WHERE before the groups, HAVING after."

8 · Connect the Dots

Lesson 3.3.4 finished NULL logic; this lesson added aggregates and grouping. Next: SQL's explicit JOIN syntax, including the outer joins of Lesson 3.1.4.

9 · Self-Test

GATE format. Try every question before opening the vault.

Q1 · NAT · 1 mark(s) — COUNT

On STUDENT (5 rows, Esha's cgpa NULL), what is COUNT(cgpa)?

Numerical answer: ________

Q2 · NAT · 2 mark(s) — AVG

What is AVG(cgpa) for dept = 'CS' rows? (Asha 9.1, Chirag 8.4, Esha NULL)

Numerical answer: ________

Q3 · NAT · 2 mark(s) — GROUP BY / HAVING

How many rows: SELECT dept FROM STUDENT GROUP BY dept HAVING COUNT(cgpa) = 1;

Numerical answer: ________

Q4 · MCQ · 1 mark(s) — Errors

Which query is invalid?

  1. (A) SELECT dept, COUNT(*) FROM STUDENT GROUP BY dept;
  2. (B) SELECT dept FROM STUDENT GROUP BY dept HAVING AVG(cgpa) > 7;
  3. (C) SELECT COUNT(*) FROM STUDENT;
  4. (D) SELECT dept, name FROM STUDENT GROUP BY dept;

Q5 · MCQ · 2 mark(s) — Empty input

SELECT COUNT(*), MAX(cgpa) FROM STUDENT WHERE dept = 'CE'; (no CE students) returns:

  1. (A) one row (NULL, NULL)
  2. (B) no rows
  3. (C) one row (0, 0)
  4. (D) one row (0, NULL)

10 · Rule Card

  • COUNT(*) counts rows; COUNT(col), SUM, AVG, MIN, MAX ignore NULL; AVG = SUM/COUNT(col).
  • Empty input: COUNT 0, others NULL; no GROUP BY → exactly one row.
  • GROUP BY: one row per group; SELECT only grouping columns + aggregates; NULLs form one group.
  • WHERE filters rows (no aggregates); HAVING filters groups.
  • Order: FROM → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY.

11 · Concept Ledger

Unlocked in this lesson. From here on, these terms may be used.

aggregate functionCOUNT(*) vs COUNT(col)COUNT(DISTINCT)SUMAVGMINMAXGROUP BYHAVINGWHERE vs HAVINGfull evaluation order

12 · Answer Vault

Reveal answers when you’re ready

Recall Warm-up

  1. UNKNOWN; FALSE.
  2. Yes, unless DISTINCT is used.
  3. Aggregation (COUNT, SUM, AVG, MIN, MAX), optionally per group.

Self-Test

Q1 Answer: 4 · 1 mark(s)

NULL skipped.

Re-read: Lesson 3.3.5 — Aggregates, GROUP BY, HAVING; COUNT(*) vs COUNT(col); NULL handling

Q2 Answer: 8.75 · 2 mark(s)

(9.1 + 8.4) / 2.

Re-read: Lesson 3.3.5 — Aggregates, GROUP BY, HAVING; COUNT(*) vs COUNT(col); NULL handling

Q3 Answer: 2 · 2 mark(s)

CS has COUNT(cgpa) = 2; EE 1; ME 1. Result: EE, ME.

Re-read: Lesson 3.3.5 — Aggregates, GROUP BY, HAVING; COUNT(*) vs COUNT(col); NULL handling

Q4 Answer: (D) · 1 mark(s)

name is neither grouped nor aggregated.

  • (A) is wrong: Valid.
  • (B) is wrong: Valid.
  • (C) is wrong: Valid.

Re-read: Lesson 3.3.5 — Aggregates, GROUP BY, HAVING; COUNT(*) vs COUNT(col); NULL handling

Q5 Answer: (D) · 2 mark(s)

An aggregate query without GROUP BY always returns one row; COUNT gives 0, MAX gives NULL.

  • (A) is wrong: COUNT is 0.
  • (B) is wrong: Aggregates without GROUP BY return one row.
  • (C) is wrong: MAX is NULL.

Re-read: Lesson 3.3.5 — Aggregates, GROUP BY, HAVING; COUNT(*) vs COUNT(col); NULL handling

Ready for the next idea?

Mark this item complete when you’ve finished reading and working through it.