COUNT(*) vs COUNT(column) — в чём разница
Коротко
COUNT(*) считает количество всех строк, включая строки с NULL. COUNT(column) считает только строки, где значение в указанной колонке не NULL.
Пример
Таблица users:
| id | name | |
|---|---|---|
| 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).