COUNT(*) vs COUNT(column) — в чём разница

Коротко

COUNT(*) считает количество всех строк, включая строки с NULL. COUNT(column) считает только строки, где значение в указанной колонке не NULL.

Пример

Таблица users:

id name email
1 Анна anna@mail.ru
2 Борис NULL
3 Вика vika@mail.ru
4 Глеб NULL
SELECT
  COUNT(*) AS total_rows,
  COUNT(email) AS with_email,
  COUNT(name) AS with_name
FROM users;
total_rows with_email with_name
4 2 4
  • COUNT(*) = 4 — все строки
  • COUNT(email) = 2 — только строки с не-NULL email
  • COUNT(name) = 4 — у всех есть имя

Ключевые отличия

COUNT(*) COUNT(column)
NULL значения Считает Пропускает
Что считает Строки Не-NULL значения в колонке
Производительность Может быть быстрее Проверяет каждое значение на NULL
Типичное использование Общее количество записей Заполненность колонки

Ещё есть COUNT(DISTINCT column)

COUNT(DISTINCT column) считает количество уникальных не-NULL значений:

SELECT
  COUNT(*) AS total_orders,
  COUNT(customer_id) AS orders_with_customer,
  COUNT(DISTINCT customer_id) AS unique_customers
FROM orders;
total_orders orders_with_customer unique_customers
1000 980 350

Частая ловушка на собеседовании

-- Задача: посчитать процент заполненности email
SELECT
  COUNT(email) * 100.0 / COUNT(*) AS fill_rate
FROM users;

Если кандидат напишет COUNT(*) в обоих местах — получит 100%. Ключ — понимать, что COUNT(email) пропускает NULL.

Запомните: COUNT(*) считает строки, COUNT(column) считает значения. Это разные вещи.

Производительность

COUNT() может быть быстрее, потому что СУБД не нужно проверять значения на NULL — достаточно знать количество строк. В PostgreSQL для таблиц без условия WHERE оба работают примерно одинаково, но в других СУБД (MySQL InnoDB) COUNT() иногда оптимизируется через индекс.

Вопросы с собеседований

  • «В таблице есть NULL в колонке middle_name. Что вернёт COUNT(middle_name)?» — Количество строк, где middle_name не NULL.
  • «Как посчитать количество NULL в колонке?» — COUNT(*) - COUNT(column).
  • «COUNT(1) и COUNT() — одно и то же?» — Да, на практике идентичны. COUNT(1) считает строки, как и COUNT().

FAQ

COUNT(0), COUNT(1), COUNT('x') — это то же самое, что COUNT(*)?

Да. Любое константное выражение внутри COUNT даёт количество строк, потому что константа никогда не NULL.

Можно ли использовать COUNT с FILTER?

В PostgreSQL да: COUNT(*) FILTER (WHERE status = 'active') — считает только строки с условием. Эквивалент SUM(CASE WHEN status = 'active' THEN 1 END).

COUNT(*) считает дубликаты?

Да. COUNT(*) считает все строки, включая полные дубликаты. Если нужны уникальные — используйте COUNT(DISTINCT column).