SQL Tutorial – Lesson 15

SQL COUNT Function – Complete Guide with Examples (2026-27)

The SQL COUNT() function is an aggregate function that returns the number of rows matching a specified condition. It is one of the most commonly used SQL functions in data analysis, reporting, and everyday database work. COUNT has three main forms: COUNT(*) counts every row including NULLs, COUNT(column) counts only non-NULL values, and COUNT(DISTINCT column) counts only unique values. In this beginner-friendly guide you will learn all three forms with eight real examples — including COUNT with WHERE, GROUP BY, HAVING, aliases, and multiple aggregates — plus key points and common mistakes to avoid.



✅ What is the SQL COUNT Function?

The SQL COUNT() function is an aggregate function that counts the number of rows in a table or in a group. It is used heavily in reporting, analytics, and everyday database queries.

COUNT(*) — counts all rows including those with NULL values and duplicates.

COUNT(column) — counts only rows where the specified column is NOT NULL.

COUNT(DISTINCT column) — counts only unique non-NULL values in the column.

✅ COUNT is supported in all databases — MySQL, PostgreSQL, SQL Server, Oracle, and SQLite — with identical syntax.

💡 Real-world uses of COUNT:
→ How many employees are in the company? — COUNT(*)
→ How many employees have an email address? — COUNT(Email)
→ How many unique departments exist? — COUNT(DISTINCT Department)
→ How many employees per department? — COUNT(*) + GROUP BY

Sample Employees Table – used in all examples below:-

Employees
IDNameDepartmentSalaryCityEmail
1ANNIIT10000Mumbaianni@mail.com
2POOJAIT9000Punepooja@mail.com
3RAJSALES5000DelhiNULL
4SUJANHR8000Punesujan@mail.com
5MEENASALES12000MumbaiNULL
6PRAMODIT15000Bangalorepramod@mail.com
7NILESHHR7000Mumbainilesh@mail.com

Note: RAJ (ID 3) and MEENA (ID 5) have NULL in the Email column — key for COUNT(Email) examples.


✅ SQL COUNT Syntax – All Three Forms

Form 1 – COUNT(*): Count All Rows

SELECT COUNT(*)
FROM table_name
WHERE condition;

Form 2 – COUNT(column): Count Non-NULL Values Only

SELECT COUNT(column_name)
FROM table_name
WHERE condition;

Form 3 – COUNT(DISTINCT column): Count Unique Values

SELECT COUNT(DISTINCT column_name)
FROM table_name
WHERE condition;
ℹ️ Database support: All three COUNT() forms work identically in MySQL, PostgreSQL, SQL Server, Oracle, and SQLite — no database-specific syntax differences.

✅ COUNT(*) vs COUNT(column) vs COUNT(DISTINCT) – Quick Comparison

FormCountsNULLs Included?Duplicates Included?Result (our table)
COUNT(*)All rows✅ Yes✅ Yes7
COUNT(Email)Non-NULL Email values❌ No✅ Yes5
COUNT(DISTINCT Department)Unique departments❌ No❌ No3

✅ Example 1 – COUNT(*): Count All Rows in the Table

Find the total number of employees — every row including those with NULL values:

SELECT Query:-

SELECT COUNT(*) FROM Employees;

Result Show:-

Result – Total Employee Count
COUNT(*)
7
ℹ️ Explanation: COUNT(*) counted all 7 rows. It looks at no specific column — it simply counts each row. Even RAJ and MEENA who have NULL emails are included because COUNT(*) ignores whether column values are NULL.

✅ Example 2 – COUNT(column): Count Non-NULL Values Only

Count how many employees have an email address on file. Rows where Email is NULL are automatically skipped:

SELECT Query:-

SELECT COUNT(Email) AS EmployeesWithEmail
FROM Employees;

Result Show:-

Result – Employees with Email
EmployeesWithEmail
5
⚠️ Key difference from COUNT(*): The table has 7 rows but COUNT(Email) returned 5. RAJ (ID 3) and MEENA (ID 5) both have NULL Email — COUNT(column) automatically skips NULLs. Use COUNT(*) when you need to count all rows including NULL ones.

✅ Example 3 – COUNT with Alias (AS)

Without an alias the result column header shows COUNT(*) — hard to read. Use AS to name it clearly:

SELECT Query:-

SELECT COUNT(*) AS TotalEmployees
FROM Employees;

Result Show:-

Result
TotalEmployees
7

Multiple COUNT values in one query:-

SELECT
  COUNT(*)                    AS TotalRows,
  COUNT(Email)                AS HaveEmail,
  COUNT(*) - COUNT(Email)     AS MissingEmail
FROM Employees;

Result Show:-

Result – Data Completeness Check
TotalRowsHaveEmailMissingEmail
752
💡 Pro tip: COUNT(*) - COUNT(column) is a powerful pattern to count NULL values in any column — very useful for data quality and completeness checks.

✅ Example 4 – COUNT with WHERE Clause

Use WHERE to filter rows before counting. Only matching rows are counted:

Example – Count only IT department employees:-

SELECT COUNT(*) AS IT_Employees
FROM Employees
WHERE Department = 'IT';

Result Show:-

Result – IT Employee Count
IT_Employees
3

Example – Count employees with salary greater than 8000:-

SELECT COUNT(*) AS HighEarners
FROM Employees
WHERE Salary > 8000;

Result Show:-

Result – Employees with Salary > 8000
HighEarners
4
ℹ️ Explanation: ANNI (10000), POOJA (9000), MEENA (12000), and PRAMOD (15000) earn more than 8000 — COUNT returns 4. SUJAN (8000) is not included because 8000 is not strictly greater than 8000.

✅ Example 5 – COUNT(DISTINCT): Count Unique Values

Count how many unique departments exist — IT appears 3 times but is counted only once:

SELECT Query:-

SELECT COUNT(DISTINCT Department) AS UniqueDepartments
FROM Employees;

Result Show:-

Result – Unique Departments
UniqueDepartments
3

Example – Count unique cities:-

SELECT COUNT(DISTINCT City) AS UniqueCities
FROM Employees;

Result Show:-

Result – Unique Cities
UniqueCities
4
ℹ️ How it works: Department has IT, IT, SALES, HR, SALES, IT, HR — 7 total but only 3 unique (IT, SALES, HR). City has Mumbai, Pune, Delhi, Pune, Mumbai, Bangalore, Mumbai — 4 unique cities.

✅ Example 6 – COUNT with GROUP BY

Use GROUP BY to count rows per category — the most widely used COUNT pattern in real-world SQL:

Example – Count employees per department:-

SELECT Department,
       COUNT(*) AS TotalEmployees
FROM Employees
GROUP BY Department
ORDER BY TotalEmployees DESC;

Result Show:-

Result – Employee Count per Department
DepartmentTotalEmployees
IT3
HR2
SALES2

Example – Count employees per city:-

SELECT City,
       COUNT(*) AS EmployeeCount
FROM Employees
GROUP BY City
ORDER BY EmployeeCount DESC;

Result Show:-

Result – Employee Count per City
CityEmployeeCount
Mumbai3
Pune2
Delhi1
Bangalore1
💡 How GROUP BY works with COUNT: GROUP BY splits the table into separate groups, then COUNT(*) is calculated independently inside each group. The final result has one row per group with its count value.

✅ Example 7 – COUNT with HAVING

Use HAVING to filter groups after GROUP BY — show only groups where the count meets a condition:

Example – Departments with more than 1 employee:-

SELECT Department,
       COUNT(*) AS TotalEmployees
FROM Employees
GROUP BY Department
HAVING COUNT(*) > 1
ORDER BY TotalEmployees DESC;

Result Show:-

Result – Departments with More than 1 Employee
DepartmentTotalEmployees
IT3
HR2
SALES2

Example – Cities with exactly 1 employee:-

SELECT City,
       COUNT(*) AS EmployeeCount
FROM Employees
GROUP BY City
HAVING COUNT(*) = 1;

Result Show:-

Result – Cities with Only 1 Employee
CityEmployeeCount
Delhi1
Bangalore1
⚠️ HAVING — not WHERE — for aggregate filters:
Wrong: WHERE COUNT(*) > 1 — syntax error.
Correct: HAVING COUNT(*) > 1
WHERE filters individual rows before grouping. HAVING filters whole groups after GROUP BY.

✅ Example 8 – COUNT with Multiple Aggregate Functions

Combine COUNT with MIN, MAX, and AVG in one query to build a complete department summary report:

SELECT Query:-

SELECT
  Department,
  COUNT(*)    AS TotalEmployees,
  MIN(Salary) AS LowestSalary,
  MAX(Salary) AS HighestSalary,
  AVG(Salary) AS AvgSalary
FROM Employees
GROUP BY Department
ORDER BY TotalEmployees DESC;

Result Show:-

Result – Full Department Summary Report
DepartmentTotalEmployeesLowestSalaryHighestSalaryAvgSalary
IT390001500011333.33
HR2700080007500.00
SALES25000120008500.00
💡 This is the standard SQL reporting pattern — combining COUNT, MIN, MAX, and AVG with GROUP BY gives a complete statistical summary per category. This is used daily in business intelligence and data analysis work.

✅ Key Points to Remember

✅ COUNT(*) counts all rows — including NULLs and duplicates. Use it for total row count.

✅ COUNT(column) skips NULLs — only rows where the column has a value are counted.

✅ COUNT(DISTINCT column) counts unique values — duplicates counted only once.

✅ Always use AS to name the resultCOUNT(*) AS TotalEmployees for readable reports.

✅ WHERE filters before counting — limits which rows COUNT sees.

✅ GROUP BY counts per group — one count per department, city, product, etc.

✅ HAVING — not WHERE — filters count resultsHAVING COUNT(*) > 2 after GROUP BY.

✅ COUNT always returns an integer — never NULL. Empty results return 0.

✅ Works in all databases — MySQL, PostgreSQL, SQL Server, Oracle, SQLite — identical syntax.


✅ Common SQL COUNT Mistakes to Avoid

❌ Mistake 1: Using WHERE instead of HAVING to filter COUNT results
Wrong: WHERE COUNT(*) > 2 — syntax error, COUNT cannot be used inside WHERE.
Correct: HAVING COUNT(*) > 2 — HAVING is evaluated after GROUP BY.
❌ Mistake 2: Confusing COUNT(*) with COUNT(column) when NULLs exist
If a column has NULL values, COUNT(*) and COUNT(column) return different numbers.
COUNT(*) = 7 (all rows), COUNT(Email) = 5 (skips 2 NULL emails). Always choose the right form.
❌ Mistake 3: Selecting non-aggregated columns without GROUP BY
Wrong: SELECT Department, COUNT(*) FROM Employees; — SQL doesn't know which Department to show.
Correct: SELECT Department, COUNT(*) FROM Employees GROUP BY Department;
❌ Mistake 4: Using COUNT(DISTINCT *) — invalid syntax
Wrong: COUNT(DISTINCT *) — not valid SQL.
Correct: Use COUNT(*) for all rows, or COUNT(DISTINCT column_name) for unique values.
❌ Mistake 5: Expecting COUNT to return NULL for empty sets
COUNT always returns an integer. If no rows match the WHERE condition, COUNT returns 0 — not NULL. Important when using COUNT in calculations or conditional logic.

✅ Frequently Asked Questions (FAQ)

What does the SQL COUNT function do?
The SQL COUNT() function is an aggregate function that returns the number of rows matching a condition. COUNT(*) counts all rows including NULLs. COUNT(column) counts only non-NULL values. COUNT(DISTINCT column) counts unique non-NULL values only.
What is the difference between COUNT(*) and COUNT(column)?
COUNT(*) counts every row regardless of NULLs. COUNT(column_name) skips rows where that column is NULL. If 7 employees exist but 2 have no email: COUNT(*) = 7 but COUNT(Email) = 5 — because 2 NULL emails are skipped.
What does COUNT(DISTINCT column) do in SQL?
COUNT(DISTINCT column) counts only unique non-NULL values. Duplicates are counted once. If Department has IT, IT, HR, SALES — COUNT(DISTINCT Department) = 3 (three unique departments, IT counted once).
Can I use COUNT with GROUP BY?
Yes. COUNT() with GROUP BY is one of the most common SQL patterns. SELECT Department, COUNT(*) AS Total FROM Employees GROUP BY Department; returns employee count for each department — one result row per department.
Can I use COUNT with WHERE?
Yes. SELECT COUNT(*) FROM Employees WHERE Department='IT'; counts only IT employees. WHERE filters rows first, then COUNT counts the filtered set.
What is the difference between WHERE and HAVING with COUNT?
WHERE filters individual rows before grouping. HAVING filters grouped results after GROUP BY using aggregate functions. Use HAVING COUNT(*) > 2 — not WHERE COUNT(*) > 2 — which causes a syntax error.

✍️ About the Author: Pramod Behera

Pramod Behera is a SAP and SQL educator with 10+ years of experience in enterprise software and database systems. He founded LearnToSAP.com to help beginners learn SAP and SQL concepts through clear, practical, real-world examples. His tutorials have helped thousands of students and IT professionals across India and beyond.