Как в запросе 1С обработать битые ссылки, NULL и Неопределено для корректного вывода в отчетах

Программист 1С v8.3 (Управляемые формы) Управленческий учет IT и автоматизация бизнеса
← На главную

В процессе разработки и сопровождения систем на базе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда данные в регистрах оказываются «загрязнены». Это могут быть «битые ссылки» (объект удален, но ссылка на него осталась), значения Неопределено, NULL или просто пустые строки в полях, где ожидается ссылка на справочник или документ. Особенно остро эта проблема встает при построении отчетов в Системе компоновки данных (СКД), когда из-за разницы в типах данных строки не группируются (не «схлопываются»), а ресурсы выводятся некорректно.

В этой статье мы подробно разберем, как нормализовать данные непосредственно в запросе, проанализируем различные подходы и выясним, какой из них наиболее оптимален с точки зрения производительности.

Понимание природы «некорректных» данных

Прежде чем приступать к написанию кода, давайте разберем, с какими именно типами «пустоты» мы имеем дело в 1С. Это критически важно для выбора правильного метода проверки:

Решение 1: Проверка через обращение к ссылке (метод «точки»)

Рассмотрим один из самых популярных и простых способов определения «битых» ссылок. Суть заключается в том, что при попытке обратиться к полю Ссылка у несуществующего объекта, система SQL вернет NULL.

Проанализируем пример кода для запроса:


ВЫБРАТЬ
    ВЫБОР
        КОГДА ДвижениеТМЦ.Заказ.Ссылка IS NULL 
            ТОГДА НЕОПРЕДЕЛЕНО
        ИНАЧЕ ДвижениеТМЦ.Заказ
    КОНЕЦ КАК ИсправленныйЗаказ
ИЗ
    РегистрНакопления.ДвижениеТМЦ КАК ДвижениеТМЦ

Важный нюанс: Этот метод универсален. Если Заказ равен NULL, Неопределено или является «битой ссылкой», проверка Заказ.Ссылка IS NULL вернет истину. Однако у этого метода есть существенный минус — производительность. При обращении через «точку» к ссылочному полю, 1С генерирует LEFT JOIN к таблице этого объекта. Если поле Заказ имеет составной тип, включающий 10 видов документов, система создаст 10 соединений, что значительно замедлит выполнение запроса на больших объемах данных.

Решение 2: Использование функции ТИПЗНАЧЕНИЯ

Для оптимизации запроса, особенно когда мы работаем с составными типами данных, лучше использовать функцию ТИПЗНАЧЕНИЯ. Она работает быстрее, так как информация о типе хранится непосредственно в таблице регистра и не требует обращения к физическим таблицам документов или справочников.

Посмотрим на пример реализации:


ВЫБРАТЬ
    ВЫБОР
        КОГДА ТИПЗНАЧЕНИЯ(ДвижениеТМЦ.Заказ) = ТИП(Документ.ЗаказПокупателя)
            ТОГДА ДвижениеТМЦ.Заказ
        ИНАЧЕ НЕОПРЕДЕЛЕНО
    КОНЕЦ КАК ИсправленныйЗаказ
ИЗ
    РегистрНакопления.ДвижениеТМЦ КАК ДвижениеТМЦ

Если типов может быть несколько, мы можем перечислить их через оператор ИЛИ или использовать проверку на вхождение в список типов. Это позволит отсечь все лишние значения (строки, NULL, другие типы), превратив их в Неопределено.

Решение 3: Универсальная очистка через массив пустых ссылок

Иногда требуется очистить данные от всех видов «пустоты»: пустых ссылок разных типов, пустых строк и Неопределено. В этом случае удобно подготовить массив некорректных значений и передать его в запрос как параметр.

Разберем этот алгоритм по шагам:

  1. В коде на языке 1С сформируем массив, включив туда Неопределено, пустую строку и пустые ссылки всех возможных типов для данного поля.
  2. Передадим этот массив в запрос.

Пример кода запроса:


ВЫБРАТЬ
    ВЫБОР
        КОГДА ДвижениеТМЦ.Модель В (&МассивПустыхЗначений)
            ТОГДА НЕОПРЕДЕЛЕНО
        ИНАЧЕ ДвижениеТМЦ.Модель
    КОНЕЦ КАК МодельИсправленная
ИЗ
    РегистрНакопления.ДвижениеТМЦ КАК ДвижениеТМЦ

Этот метод считается одним из самых надежных, так как он явно обрабатывает все возможные варианты «мусора» в данных, не нагружая систему лишними соединениями таблиц.

Решение 4: Применение конструкции ЗНАЧЕНИЕ

Если нам нужно проверить значение на конкретную пустую ссылку, не передавая параметры извне, мы можем использовать конструкцию ЗНАЧЕНИЕ. Это выполняется на уровне сервера приложений и работает очень эффективно.

Рассмотрим пример:


ВЫБОР 
    КОГДА ДвижениеТМЦ.Заказ = ЗНАЧЕНИЕ(Документ.ЗаказПокупателя.ПустаяСсылка) 
        ТОГДА НЕОПРЕДЕЛЕНО 
    ИНАЧЕ ДвижениеТМЦ.Заказ 
КОНЕЦ

Проблема группировки в виртуальных таблицах

Выясним важную причину, по которой отчеты могут «двоить» строки, даже если визуально значения в колонках кажутся одинаковыми. Если вы используете виртуальную таблицу ОстаткиИОбороты, группировка данных происходит на уровне самой таблицы по измерениям. Если в базе в одном случае записано NULL, а в другом — Неопределено, виртуальная таблица выдаст две разные строки.

Даже если в блоке ВЫБРАТЬ вы напишете ВЫБОР... и приведете их к одному виду (например, оба значения станут Неопределено), в результате запроса все равно останется две строки с одинаковым названием. Чтобы «схлопнуть» эти строки, необходимо выполнить следующие действия:

  1. Выбрать данные из виртуальной таблицы во временную таблицу, нормализовав значения измерений с помощью конструкций ВЫБОР.
  2. Вторым запросом выбрать данные из этой временной таблицы, используя СГРУППИРОВАТЬ ПО всем измерениям и просуммировав ресурсы (Количество, Сумма).

Только такой подход гарантирует, что все «некорректные» записи будут объединены в одну строку Неопределено.

Использование возможностей СКД

Если правка самого текста запроса затруднительна, мы можем воспользоваться инструментами Системы компоновки данных. На закладке «Наборы данных» в поле «Выражение» для нужного поля можно написать условие на языке выражений СКД.

Например, если в конфигурации используется Библиотека стандартных подсистем (БСП), можно вызвать функцию общего модуля:

ОбщегоНазначения.ЗначениеЗаполнено(Заказ)

Однако помните: Вызов функций общих модулей в СКД может существенно замедлить формирование отчета, так как эта функция будет вызываться для каждой строки результата запроса. Поэтому предпочтительным методом всегда остается исправление данных непосредственно в тексте запроса на языке SQL.

Подводя итог, проанализируем ситуацию: для простых проверок на «битые ссылки» подходит метод .Ссылка IS NULL, для оптимизированных отчетов по составным типам — ТИПЗНАЧЕНИЯ, а для гарантированной группировки данных в регистрах всегда используйте предварительную нормализацию во временных таблицах.

← На главную