Собесов

COUNT(*) vs COUNT(col): как считаются NULL

SQLNULL и трёхзначная логикаЛёгкаяJunior

Условие

Как функция COUNT(*) работает с NULL-значениями? Чем она отличается от COUNT(col)?

Решение

Выражение Что считает
COUNT(*) Все строки, включая те, где все колонки NULL
COUNT(1) То же, что COUNT(*)
COUNT(col) Только строки, где col IS NOT NULL
COUNT(DISTINCT col) Уникальные не-NULL значения

Пример

-- таблица employees
-- id | name  | manager_id
-- 1  | Иван  | NULL          ← без менеджера
-- 2  | Маша  | 1
-- 3  | Петя  | 1
-- 4  | NULL  | 2
 
SELECT
  COUNT(*)              AS total,                -- 4
  COUNT(name)           AS with_name,            -- 3 (NULL не учитывается)
  COUNT(manager_id)     AS with_manager,         -- 3
  COUNT(DISTINCT manager_id) AS uniq_managers    -- 2 (1 и 2)
FROM employees;

Применение

-- сколько сотрудников БЕЗ менеджера
SELECT COUNT(*) - COUNT(manager_id) AS no_manager FROM employees;
 
-- то же через FILTER (PostgreSQL) или CASE
SELECT COUNT(*) FILTER (WHERE manager_id IS NULL) FROM employees;
SELECT SUM(CASE WHEN manager_id IS NULL THEN 1 ELSE 0 END) FROM employees;

Фишка с COUNT(DISTINCT) и NULL

SELECT COUNT(DISTINCT col) FROM (VALUES (1),(1),(2),(NULL),(NULL)) t(col);
-- 2: NULL'ы вообще не считаются как «значение»

Подводные камни

  1. COUNT(col1, col2) работает не везде. В PostgreSQL — синтаксическая ошибка. В некоторых СУБД считает строки, где обе колонки не-NULL.
  2. AVG(col), SUM(col), MIN(col) тоже игнорируют NULL — может казаться, что данные «потерялись».
  3. COUNT(*) OVER () в оконной функции — считает все строки в рамках партиции, без учёта NULL в выражении.

Эталонный ответ

COUNT(*) считает все строки, включая полностью NULL. COUNT(col) игнорирует NULL в этой колонке. COUNT(DISTINCT col) — уникальные не-NULL значения.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти