← На главную
SQL · АВТОРСКИЙ УЧЕБНЫЙ РАЗБОР

Почему COUNT возвращает разные числа: NULL в SQL

Три строки в таблице не всегда означают три значения в колонке. Разберём разницу, которая влияет на отчёты и ответы на собеседовании.

Один набор данных

Представь три заказа. В колонке discount записаны значения 0, 10 и NULL. Ноль здесь означает известную скидку в ноль рублей. NULL — отсутствие известного значения. Это разные ситуации.

COUNT(*) → 3
COUNT(discount) → 2
COUNT(DISTINCT discount) → 2

COUNT(*) считает строки. COUNT(discount) — строки с непустым, то есть не NULL, значением в этой колонке. DISTINCT оставляет уникальные известные значения: в нашем примере это 0 и 10.

Где появляется ошибка

Если назвать COUNT(discount) количеством заказов, отчёт потеряет третий заказ. Если заменить NULL на ноль без обсуждения смысла, мы заявим, что у третьего заказа скидки не было. Но исходные данные этого не говорят.

Аналитик сначала уточняет значение пропуска. Скидка неизвестна из-за ошибки загрузки? Поле не заполняется для части заказов? Или по правилам системы пропуск действительно означает отсутствие скидки? От этого зависит обработка.

Ещё один пример: среднее

AVG(discount) для этих значений даст 5: (0 + 10) / 2. Если сознательно заменить NULL на 0, среднее станет 10 / 3. Оба вычисления возможны, но отвечают на разные вопросы.

Как объяснить на собеседовании

  1. Назови, что считаешь: строки, известные значения или уникальные значения.
  2. Отдельно объясни поведение NULL.
  3. Покажи маленький пример, где результаты расходятся.
  4. Уточни бизнес-смысл пропуска, прежде чем выбирать обработку.

Проверь себя

Добавь ещё одну строку со скидкой 10. Теперь COUNT(*) равен 4, COUNT(discount) — 3, а COUNT(DISTINCT discount) по-прежнему 2. Попробуй объяснить каждое число своими словами.

Пример использует обычное поведение SQL-агрегатов, в частности PostgreSQL. Это авторский учебный материал, без привязки к конкретной компании.

Хочешь разобрать свою ситуацию вместе?

Написать Никите ↗