Однажды при подготовке нового дашборда выяснилось, что старый SQL-запрос даёт странные данные. Коллега заметил аномалию в одном из разрезов — и это потянуло за собой неочевидную, но серьёзную ошибку в логике JOIN.
Что произошло
Две таблицы соединялись по ID заявки. В левой таблице было 5 миллионов строк, у которых ID равнялся нулю — и это само по себе было допустимо по бизнес-логике. В правой таблице оказалась ровно одна запись с нулевым ID, которую следовало отфильтровать заранее, но этого сделано не было.
В результате JOIN отработал формально корректно: все 5 миллионов строк с нулём в левой таблице совпали с единственной нулевой записью в правой. Каждой из них были присвоены данные этой одной записи. Ошибка не породила пустых строк и не вызвала явного сбоя — запрос выполнился без ошибок.
Почему ошибку не заметили сразу
Строки с нулевым ID равномерно распределялись по всем датам, поэтому на временном графике не было характерного пика или провала, который сразу бросился бы в глаза. Визуально данные выглядели правдоподобно.
Несостыковку удалось обнаружить только потому, что внимательный коллега заметил провалы по выходным дням в одном из разрезов. Эта особенность была связана с реальным графиком работы сотрудников — и именно она стала индикатором того, что данные подмешиваются некорректно.
В чём суть проблемы
NULL и нулевые значения (0) в ключевых колонках ведут себя по-разному, но в обоих случаях могут создавать нежелательные совпадения при JOIN. Нулевой ID — это не «отсутствие данных» в смысле NULL, однако логически он часто означает «неизвестно» или «не применимо». Если в обеих таблицах есть строки с таким значением, JOIN их объединит — даже если семантически это неверно.
Что сделать на практике
- Перед написанием JOIN проверяйте распределение значений в ключевой колонке с обеих сторон — особенно наличие NULL и нулей.
- Если нулевые или NULL-значения не несут смысловой нагрузки для соединения, фильтруйте их явно в WHERE или подзапросе до JOIN.
- После построения дашборда сверяйте агрегированные метрики с исходными таблицами — расхождение в количестве строк сигнализирует о проблеме.
- Используйте разрезы с ожидаемыми закономерностями (день недели, рабочий/нерабочий период) как контрольные точки для валидации данных.
- Документируйте допустимые значения ключевых полей: какие ID считаются валидными, а какие — техническим мусором, который нужно исключать.
Вывод
NULL и нулевые значения в колонках JOIN — одна из самых коварных причин тихих ошибок в данных. Они не ломают запрос, не бросаются в глаза на графике и обнаруживаются только при внимательном анализе в нескольких разрезах. Проверка ключевых колонок на нули должна быть частью стандартного code review любого SQL-запроса, который идёт в продакшн.
