Skip to content
Laviyx Learn

Try

SQL course menu

SQL COUNT(): Count Rows, Values and Unique Values

Learn the SQL COUNT function: COUNT(*) vs COUNT(column) vs COUNT(DISTINCT column), counting with WHERE, counting per group with GROUP BY, and how NULLs affect the result.

Beginner5 min readUpdated
On this page

"How many?" is one of the most common questions you will ask a database. How many customers do we have? How many orders this month? How many employees in each department? COUNT answers all of them.

The example table#

idnamedepartmentsalarymanager_id
1AshaSales520005
2RaviEngineering780003
3MeeraEngineering81000NULL
4JohnMarketing460005
5PriyaSales61000NULL

Count all rows#

SQLRun
SELECT COUNT(*) AS employees
FROM employees;
Output
employees
---------
5

COUNT is an aggregate function: it takes many rows and returns one value.

Count rows that match a condition#

WHERE filters first, then COUNT counts what is left:

SQLRun
SELECT COUNT(*) AS engineers
FROM employees
WHERE department = 'Engineering';
Output
engineers
---------
2

Three kinds of COUNT#

FormCounts
COUNT(*)every row, no matter what it contains
COUNT(column)rows where column is not NULL
COUNT(DISTINCT column)different non-NULL values in column
SQLRun
SELECT COUNT(*)                   AS all_rows,
       COUNT(manager_id)          AS with_manager,
       COUNT(DISTINCT department) AS departments
FROM employees;
Output
all_rows | with_manager | departments
---------+--------------+------------
5        | 3            | 3

Meera and Priya have no manager, so COUNT(manager_id) is 3, not 5. This difference matters a lot after a LEFT JOIN, where unmatched rows contain NULLs.

Count per group#

Combine COUNT with GROUP BY to count each group separately:

SQLRun
SELECT department, COUNT(*) AS employees
FROM employees
GROUP BY department
ORDER BY employees DESC, department;
Output
department  | employees
------------+----------
Engineering | 2
Sales       | 2
Marketing   | 1

COUNT never returns NULL#

When no rows match, COUNT returns 0, unlike SUM and AVG, which return NULL:

SQLRun
SELECT COUNT(*) AS big_orders
FROM orders
WHERE amount > 1000;
Output
big_orders
----------
0

Counting with a condition inside#

Sometimes you want several counts in one row. A CASE expression inside SUM (or COUNT) does it:

SQLRun
SELECT COUNT(*) AS total,
       SUM(CASE WHEN department = 'Sales' THEN 1 ELSE 0 END) AS in_sales
FROM employees;

This "conditional aggregation" pattern is covered in CASE. PostgreSQL also supports the neat COUNT(*) FILTER (WHERE department = 'Sales').

Common mistakes#

Practice#

Practice exercise

Using the products table (product_id, name, category, price, stock), write one query that returns:

  • the total number of products, as products
  • how many different categories there are, as categories
Show hint

COUNT(*) for the first, COUNT(DISTINCT category) for the second.

Show solution
SQLRun
SELECT COUNT(*)                 AS products,
       COUNT(DISTINCT category) AS categories
FROM products;
Output
products | categories
---------+-----------
6        | 3

The six products are spread across Electronics, Furniture and Stationery.

Key takeaway#

Finished this lesson?