SQL-Engineering-Handbook

COUNT()

Introduction

COUNT() answers the single most common question asked of any dataset: how many? It’s usually the first aggregate function anyone writes, and it’s also the one most often used incorrectly — the difference between COUNT(*), COUNT(column), and COUNT(DISTINCT column) trips up even experienced engineers under interview pressure.

Learning Objectives

By the end of this file you should be able to:

Concept Overview

COUNT() returns the number of rows matched by a query, or the number of non-NULL values in a specific column.

Form Counts
COUNT(*) Every row, including rows where every column is NULL
COUNT(column_name) Only rows where column_name is not NULL
COUNT(DISTINCT column_name) Only the number of unique non-NULL values

COUNT(*) vs COUNT(column) vs COUNT(DISTINCT column)

Business Context

Almost every dashboard has a headline number in the top-left corner — total customers, total orders, total open tickets. That number is a COUNT(). Getting it wrong (e.g., silently excluding rows with a NULL email) means shipping a dashboard that under-reports reality.

Where Companies Use It

Syntax

SELECT COUNT(*) FROM table_name;
SELECT COUNT(column_name) FROM table_name;
SELECT COUNT(DISTINCT column_name) FROM table_name;

Execution Flow

employes table
┌────────┬──────────┬─────────┐
│ emp_id │ emp_name │ dept_id │
├────────┼──────────┼─────────┤
│   1    │  Alice   │   10    │
│   2    │  Bob     │  NULL   │   <- unassigned
│   3    │  Carol   │   10    │
│   4    │  Dave    │   20    │
└────────┴──────────┴─────────┘

COUNT(*)              -> 4   (every row)
COUNT(dept_id)        -> 3   (NULL row excluded)
COUNT(DISTINCT dept_id)-> 2  (10, 20)

Engineering Notes

MySQL Notes

COUNT(DISTINCT col1, col2) is a MySQL extension — it counts distinct combinations of col1 and col2 together. This is not standard ANSI SQL.

PostgreSQL Notes

PostgreSQL does not support multi-column COUNT(DISTINCT col1, col2). Use COUNT(DISTINCT (col1, col2)) (a row constructor) instead.

Edge Cases

Common Mistakes

Wrong — assuming COUNT(column) behaves like COUNT(*):

-- Silently under-counts if manager_id has NULLs (e.g., the CEO)
SELECT COUNT(manager_id) AS total_employees FROM employes;

Correct:

SELECT COUNT(*) AS total_employees FROM employes;

Interview Questions

  1. What’s the difference between COUNT(*) and COUNT(1)? (Trick question — there isn’t one in practice.)
  2. If a table has 100 rows and a column email is NULL in 5 of them, what does COUNT(email) return?
  3. Write a query to count the number of distinct departments represented in the employes table.
  4. Why does COUNT(*) return 0 instead of NULL on an empty table, while SUM() returns NULL?

Summary

COUNT(*) counts rows. COUNT(column) counts non-NULL values in that column. COUNT(DISTINCT column) counts unique non-NULL values. Choosing the wrong form is the single most common aggregation bug in production reporting code.

Practice Challenges

  1. Write a query returning the number of employees with a non-NULL dept_id.
  2. Write a query returning the number of distinct cities employees work in (requires joining to locations).
  3. Predict — without running it — what COUNT(*) returns on the result of a LEFT JOIN where the right table has no match for some rows.

Further Reading


Related Topics: SUM() · GROUP BY · HAVING


← Previous Lesson ↑ Module README Next Lesson →