Как считать NULL и NOT NULL в SQL
NULL в SQL означает «нет значения» — не ноль и не пустая строка. Для подсчёта используйте COUNT(), COUNT(col), выражения SUM(CASE WHEN …), или разницу COUNT(*) - COUNT(col). Примеры, советы по производительности и чек-лист помогут избежать типичных ошибок.
Работа с NULL — частая задача для аналитиков и администраторов баз данных. NULL означает отсутствие значения или неизвестность, и это поведение влияет на сравнения, агрегаты и логику запросов. Ниже — понятные объяснения, примеры запросов и практические приёмы для подсчёта NULL и NOT NULL значений.
Что такое NULL в SQL?
NULL означает «нет значения» или «отсутствие данных». Это не 0 и не пустая строка. NULL ведёт себя по правилам трёхзначной логики: результат сравнения с обычными операторами (=, <, >, <>) будет UNKNOWN, а не TRUE или FALSE.
Краткое определение: NULL — отсутствие значения или неизвестное значение в поле записи.
Ментальная модель: представляйте NULL как поле, оставленное пустым при вводе записи — оно не равно ничему, пока явно не задано.
Пример таблицы и вставки
Создадим таблицу и вставим несколько строк с NULL:
CREATE TABLE Employee (
FirstName VARCHAR(50),
LastName VARCHAR(50),
PhoneNum VARCHAR(15),
Salary FLOAT
);
INSERT INTO Employee (FirstName, LastName, PhoneNum, Salary)
VALUES
('Maxwell', 'Ayomide', '812-345-6789', 150000.00),
('David', 'Tosin', NULL, 450000.00),
('Eben', 'Teniola', '912-345-6789', 590000.00),
('Kenneth', 'Olisa', '809-456-8732', NULL),
('Esther', 'Oge', NULL, NULL);Чтобы обновить значение, используйте UPDATE:
UPDATE Employee
SET FirstName = 'Esther'
WHERE Salary = 200000;И просмотреть результат:
SELECT * FROM Employee;Когда NULL полезен
NULL применяется, когда данные неизвестны, ещё не получены или неприменимы к сущности. Примеры:
- Поле телефона у клиента ещё не заполнено.
- В опросе респондент пропустил вопрос — хранится NULL.
- Для опциональных атрибутов, которые не соответствуют всем записям.
Оператор IS NULL
IS NULL используется для выбора строк с NULL:
SELECT FirstName, LastName, PhoneNum
FROM Employee
WHERE PhoneNum IS NULL;Этот запрос вернёт строки, где PhoneNum действительно отсутствует.
Оператор IS NOT NULL
IS NOT NULL возвращает строки с ненулевыми значениями:
SELECT FirstName, LastName, PhoneNum
FROM Employee
WHERE PhoneNum IS NOT NULL;Это удобный способ получить только заполненные номера телефонов.
Как посчитать NULL в столбце
Подходы к подсчёту NULL и NOT NULL:
- COUNT(колонка) — считает только ненулевые значения в колонке.
- COUNT(*) — считает все строки (включая те, где колонка NULL).
- Разница COUNT(*) - COUNT(col) даёт количество NULL в col.
- SUM(CASE WHEN col IS NULL THEN 1 ELSE 0 END) явно суммирует NULL как 1.
Пример подсчёта NULL в PhoneNum:
SELECT COUNT(*) AS [Total Rows]
FROM Employee
WHERE PhoneNum IS NULL;Другой способ — посчитать ненулевые значения:
SELECT COUNT(PhoneNum) AS [Total Number of Non-NULL Values]
FROM Employee
WHERE PhoneNum IS NOT NULL;И аккуратно в одной строке:
SELECT SUM(CASE WHEN PhoneNum IS NULL THEN 1 ELSE 0 END) AS [Number Of Null Values],
COUNT(PhoneNum) AS [Number Of Non-Null Values]
FROM Employee;Дополнительный приём: быстрее и компактно
SELECT COUNT(*) - COUNT(PhoneNum) AS NullCount,
COUNT(PhoneNum) AS NotNullCount
FROM Employee;Группировка и агрегаты
Чтобы получить количество NULL по группам:
SELECT Department,
COUNT(*) AS TotalRows,
COUNT(PhoneNum) AS NotNullPhones,
COUNT(*) - COUNT(PhoneNum) AS NullPhones
FROM Employee
GROUP BY Department;Агрегатные функции (SUM, AVG, MAX, MIN, COUNT) обычно игнорируют NULL, поэтому учитывайте это при расчётах.
Альтернативные функции для замены NULL
Для обработки NULL часто используют:
- COALESCE(col, default) — возвращает первый ненулевой аргумент.
- ISNULL(col, default) — в MS SQL заменяет NULL на default.
- NVL(col, default) — в Oracle заменяет NULL на default.
Пример замены для вывода:
SELECT FirstName, COALESCE(PhoneNum, 'не указан') AS PhoneNum
FROM Employee;Поведение в разных БД и тонкости совместимости
- COALESCE стандартен и доступен во многих СУБД. ISNULL и NVL — специфичны для MS SQL и Oracle.
- COUNT(col) и COUNT(*) работают одинаково в большинстве СУБД, но всегда полезно проверить документацию при миграции.
Частые ошибки и когда подход не сработает
- Ошибка: использование сравнения PhoneNum = NULL — всегда неверно. Нужно WHERE PhoneNum IS NULL.
- Ошибка: ожидание что COUNT(col) посчитает NULL — он их пропускает.
- Особые случаи: булевы выражения и трёхзначная логика могут дать неожиданные TRUE/UNKNOWN.
Чек-лист для аналитика
- Определите, что NULL означает в вашем наборе данных (неизвестно/неприменимо).
- Используйте IS NULL/IS NOT NULL для фильтрации.
- Для подсчёта NULL применяйте COUNT(*) - COUNT(col) или SUM(CASE …).
- При выводе заменяйте NULL через COALESCE/ISNULL/NVL для читаемости отчётов.
- Проверьте поведение агрегатов при наличии NULL.
Быстрая шпаргалка (cheat sheet)
- COUNT(*) — все строки
- COUNT(col) — только ненулевые значения col
- COUNT(*) - COUNT(col) — количество NULL в col
- SUM(CASE WHEN col IS NULL THEN 1 ELSE 0 END) — альтернативный подсчёт NULL
- COALESCE(col, default) — замена NULL на default
Пример реального сценария
Задача: посчитать, сколько клиентов не указали телефон и вывести процент.
SELECT COUNT(*) AS TotalClients,
COUNT(PhoneNum) AS ClientsWithPhone,
(COUNT(*) - COUNT(PhoneNum)) AS ClientsWithoutPhone,
ROUND(100.0 * (COUNT(*) - COUNT(PhoneNum)) / COUNT(*), 2) AS PercentWithoutPhone
FROM Customer;Важно: при делении на COUNT(*) проверяйте, что TotalClients не равен 0.
Рекомендации по производительности
- По возможности используйте индексированные колонки при фильтрации IS NOT NULL — некоторые СУБД могут использовать индексы для поиска ненулевых значений.
- SUM(CASE WHEN …) может быть чуть медленнее, чем простая арифметическая разница COUNT(*) - COUNT(col) — но читаемее для сложной логики.
Заключение
NULL — это понятие «отсутствие значения», которое требует аккуратного обращения: фильтрация через IS NULL/IS NOT NULL, подсчёт через COUNT и SUM(CASE …), замена через COALESCE. Понимание этих приёмов позволяет получать корректные метрики и избегать логических ошибок.
Важно
NULL — не значение, а его отсутствие; проверяйте логику запросов и используйте соответствующие операторы.
Краткая сводка
- COUNT(колонка) не считает NULL.
- COUNT(*) включает все строки.
- COUNT(*) - COUNT(колонка) даёт количество NULL.
- Для отображения вместо NULL используйте COALESCE.
Ресурсы
Для углублённого изучения откройте документацию вашей СУБД по COALESCE, ISNULL, NVL и поведению агрегатов.