В процессе разработки и сопровождения систем на базе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда данные в регистрах оказываются «загрязнены». Это могут быть «битые ссылки» (объект удален, но ссылка на него осталась), значения Неопределено, NULL или просто пустые строки в полях, где ожидается ссылка на справочник или документ. Особенно остро эта проблема встает при построении отчетов в Системе компоновки данных (СКД), когда из-за разницы в типах данных строки не группируются (не «схлопываются»), а ресурсы выводятся некорректно.
В этой статье мы подробно разберем, как нормализовать данные непосредственно в запросе, проанализируем различные подходы и выясним, какой из них наиболее оптимален с точки зрения производительности.
Прежде чем приступать к написанию кода, давайте разберем, с какими именно типами «пустоты» мы имеем дело в 1С. Это критически важно для выбора правильного метода проверки:
Справочник.Номенклатура), которая указывает на пустой уникальный идентификатор (все нули).Рассмотрим один из самых популярных и простых способов определения «битых» ссылок. Суть заключается в том, что при попытке обратиться к полю Ссылка у несуществующего объекта, система SQL вернет NULL.
Проанализируем пример кода для запроса:
ВЫБРАТЬ
ВЫБОР
КОГДА ДвижениеТМЦ.Заказ.Ссылка IS NULL
ТОГДА НЕОПРЕДЕЛЕНО
ИНАЧЕ ДвижениеТМЦ.Заказ
КОНЕЦ КАК ИсправленныйЗаказ
ИЗ
РегистрНакопления.ДвижениеТМЦ КАК ДвижениеТМЦ
Важный нюанс: Этот метод универсален. Если Заказ равен NULL, Неопределено или является «битой ссылкой», проверка Заказ.Ссылка IS NULL вернет истину. Однако у этого метода есть существенный минус — производительность. При обращении через «точку» к ссылочному полю, 1С генерирует LEFT JOIN к таблице этого объекта. Если поле Заказ имеет составной тип, включающий 10 видов документов, система создаст 10 соединений, что значительно замедлит выполнение запроса на больших объемах данных.
Для оптимизации запроса, особенно когда мы работаем с составными типами данных, лучше использовать функцию ТИПЗНАЧЕНИЯ. Она работает быстрее, так как информация о типе хранится непосредственно в таблице регистра и не требует обращения к физическим таблицам документов или справочников.
Посмотрим на пример реализации:
ВЫБРАТЬ
ВЫБОР
КОГДА ТИПЗНАЧЕНИЯ(ДвижениеТМЦ.Заказ) = ТИП(Документ.ЗаказПокупателя)
ТОГДА ДвижениеТМЦ.Заказ
ИНАЧЕ НЕОПРЕДЕЛЕНО
КОНЕЦ КАК ИсправленныйЗаказ
ИЗ
РегистрНакопления.ДвижениеТМЦ КАК ДвижениеТМЦ
Если типов может быть несколько, мы можем перечислить их через оператор ИЛИ или использовать проверку на вхождение в список типов. Это позволит отсечь все лишние значения (строки, NULL, другие типы), превратив их в Неопределено.
Иногда требуется очистить данные от всех видов «пустоты»: пустых ссылок разных типов, пустых строк и Неопределено. В этом случае удобно подготовить массив некорректных значений и передать его в запрос как параметр.
Разберем этот алгоритм по шагам:
Неопределено, пустую строку и пустые ссылки всех возможных типов для данного поля.Пример кода запроса:
ВЫБРАТЬ
ВЫБОР
КОГДА ДвижениеТМЦ.Модель В (&МассивПустыхЗначений)
ТОГДА НЕОПРЕДЕЛЕНО
ИНАЧЕ ДвижениеТМЦ.Модель
КОНЕЦ КАК МодельИсправленная
ИЗ
РегистрНакопления.ДвижениеТМЦ КАК ДвижениеТМЦ
Этот метод считается одним из самых надежных, так как он явно обрабатывает все возможные варианты «мусора» в данных, не нагружая систему лишними соединениями таблиц.
Если нам нужно проверить значение на конкретную пустую ссылку, не передавая параметры извне, мы можем использовать конструкцию ЗНАЧЕНИЕ. Это выполняется на уровне сервера приложений и работает очень эффективно.
Рассмотрим пример:
ВЫБОР
КОГДА ДвижениеТМЦ.Заказ = ЗНАЧЕНИЕ(Документ.ЗаказПокупателя.ПустаяСсылка)
ТОГДА НЕОПРЕДЕЛЕНО
ИНАЧЕ ДвижениеТМЦ.Заказ
КОНЕЦ
Выясним важную причину, по которой отчеты могут «двоить» строки, даже если визуально значения в колонках кажутся одинаковыми. Если вы используете виртуальную таблицу ОстаткиИОбороты, группировка данных происходит на уровне самой таблицы по измерениям. Если в базе в одном случае записано NULL, а в другом — Неопределено, виртуальная таблица выдаст две разные строки.
Даже если в блоке ВЫБРАТЬ вы напишете ВЫБОР... и приведете их к одному виду (например, оба значения станут Неопределено), в результате запроса все равно останется две строки с одинаковым названием. Чтобы «схлопнуть» эти строки, необходимо выполнить следующие действия:
ВЫБОР.Только такой подход гарантирует, что все «некорректные» записи будут объединены в одну строку Неопределено.
Если правка самого текста запроса затруднительна, мы можем воспользоваться инструментами Системы компоновки данных. На закладке «Наборы данных» в поле «Выражение» для нужного поля можно написать условие на языке выражений СКД.
Например, если в конфигурации используется Библиотека стандартных подсистем (БСП), можно вызвать функцию общего модуля:
ОбщегоНазначения.ЗначениеЗаполнено(Заказ)
Однако помните: Вызов функций общих модулей в СКД может существенно замедлить формирование отчета, так как эта функция будет вызываться для каждой строки результата запроса. Поэтому предпочтительным методом всегда остается исправление данных непосредственно в тексте запроса на языке SQL.
Подводя итог, проанализируем ситуацию: для простых проверок на «битые ссылки» подходит метод .Ссылка IS NULL, для оптимизированных отчетов по составным типам — ТИПЗНАЧЕНИЯ, а для гарантированной группировки данных в регистрах всегда используйте предварительную нормализацию во временных таблицах.