Почему в отчетах СКД пропадают значения ИНН и как использование функции ВЫРАЗИТЬ решает эту проблему?

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

При разработке отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, которую называют «мистикой»: один и тот же запрос в консоли запросов выдает полные данные, а в отчете СКД некоторые поля (например, ИНН или КПП) внезапно оказываются пустыми. Особенно часто это происходит, когда значение выбирается через конструкцию ВЫБОР или получается из левых соединений. В этой статье мы подробно разберем, почему СКД ведет себя именно так, и как правильно использовать функцию ВЫРАЗИТЬ, чтобы гарантировать вывод данных.

Проанализируем ситуацию: когда данные есть, но их не видно

Рассмотрим классический пример, с которым столкнулся автор темы. В конфигурации (например, «Управление торговлей 10.3») ИНН контрагента хранится как Строка длиной 12 символов. При построении отчета по алкогольной продукции необходимо выбрать ИНН производителя, причем логика выбора зависит от того, ведется ли учет по сериям. Напишем фрагмент запроса, который кажется абсолютно логичным:


ВЫБОР
    КОГДА КорректировкаРеализации.Номенклатура.ВестиУчетПоСериям
        ТОГДА КорректировкаРеализации.Номенклатура.Производитель.ИНН
    ИНАЧЕ КорректировкаРеализации.Номенклатура.ПроизводительЕГАИС.ИНН
КОНЕЦ КАК ВозвратИННПроизводителя

В консоли запросов такой код работает идеально: все 12 символов ИНН отображаются для каждой строки. Однако в отчете СКД часть строк приходит с пустым полем ВозвратИННПроизводителя. При этом в карточках производителей ИНН точно заполнен. Выясним причину этого поведения.

Разберем механизмы работы СКД: почему консоль — не показатель

Главное отличие консоли запросов от СКД заключается в том, что консоль выполняет запрос «как есть», просто отображая результат, который вернула СУБД. СКД — это мощный объектный механизм, который перед выполнением запроса проводит его глубокую трансформацию. Рассмотрим подробнее, что происходит «под капотом»:

  1. Оптимизация запроса. СКД анализирует, какие поля выбраны в настройках отчета, какие участвуют в группировках, а какие — в отборах. Если поле участвует в сложном условии ВЫБОР, оптимизатор может некорректно интерпретировать итоговый тип данных, особенно если поля в разных ветках ТОГДА принадлежат разным таблицам.
  2. Определение типа поля. Когда в конструкции ВЫБОР встречаются реквизиты из разных источников, или если одна из веток может вернуть NULL (из-за ЛЕВОЕ СОЕДИНЕНИЕ), СКД пытается привести результат к общему типу. В некоторых случаях этот тип определяется как «составной» или как «строка неограниченной длины».
  3. Трансформация в SQL. При генерации итогового SQL-запроса СКД может добавить свои условия или изменить структуру соединений. Если на этапе компоновки данных тип не был жестко определен, механизм отображения в макете может просто проигнорировать значение, которое не вписывается в ожидаемый формат.

Решение проблемы: магическая сила функции ВЫРАЗИТЬ

Чтобы победить «мистику» и заставить СКД выводить данные корректно, необходимо использовать явное приведение типов. Функция ВЫРАЗИТЬ сообщает системе компоновки (и СУБД), что результат данного выражения всегда должен рассматриваться как строка определенной длины. Посмотрим, как изменится наш код:


ВЫРАЗИТЬ(ВЫБОР
    КОГДА КорректировкаРеализации.Номенклатура.ВестиУчетПоСериям
        ТОГДА КорректировкаРеализации.Номенклатура.Производитель.ИНН
    ИНАЧЕ КорректировкаРеализации.Номенклатура.ПроизводительЕГАИС.ИНН
КОНЕЦ КАК СТРОКА(12)) КАК ВозвратИННПроизводителя

Использование ВЫРАЗИТЬ( ... КАК СТРОКА(12)) решает сразу несколько задач. Во-первых, оно ограничивает длину строки, предотвращая превращение поля в NVARCHAR(MAX) на уровне SQL, что критично для корректной работы группировок в СКД. Во-вторых, это дает подсказку самому процессору компоновки данных о том, какой тип ожидать в данной колонке.

Рассмотрим влияние левых соединений и значений NULL

Проанализируем полный текст запроса, приведенный в обсуждении. Мы видим активное использование ЛЕВОЕ СОЕДИНЕНИЕ с таблицами корректировок и сведений об алкогольной продукции. Если для какой-то реализации нет корректировки, все поля таблицы КорректировкаРеализации примут значение NULL.

В обычном запросе NULL в строковом поле часто визуально неотличим от пустой строки. Однако для СКД это принципиально разные сущности. Если первая запись в выборке содержит NULL, а последующие — заполненные строки, СКД может ошибочно инициализировать тип колонки в наборе данных как несовместимый с выводом строковых данных. Именно поэтому в сложных отчетах крайне рекомендуется оборачивать строковые результаты в ВЫРАЗИТЬ, даже если вы уверены, что в базе данных длина строки фиксирована.

Разберем по шагам настройку набора данных

Если после правки текста запроса данные все равно не выводятся, проанализируем настройки самого набора данных в схеме компоновки:

  1. Перейдите на закладку «Наборы данных».
  2. Найдите проблемное поле (например, ВозвратИННПроизводителя).
  3. Посмотрите в колонку «Тип». Если там указано «Составной тип» или просто «Строка» без указания длины, это потенциальное место возникновения ошибки.
  4. Попробуйте вручную снять галочку «Автозаполнение» (если это возможно в вашем контексте) или проверьте колонку «Роль». Поля, по которым не ведется суммирование, должны иметь корректно определенные типы.
  5. Обратите внимание на флаг «Обязательное». Если поле используется в сложном условии, иногда установка этого флага помогает оптимизатору СКД не «выкидывать» это поле из итогового запроса к базе данных.

Выясним причину на примере алкогольной декларации

Как упоминалось в обсуждении, проблема особенно остро встает при формировании специфической отчетности, такой как алкогольная декларация. Там важна точность каждого символа ИНН и КПП. Если производитель в справочнике один, а в документах ЕГАИС — другой, использование условий ВЫБОР неизбежно. Без жесткой типизации через ВЫРАЗИТЬ такие отчеты могут выгружаться с пустыми атрибутами производителей, что приведет к ошибкам при проверке в ФСРАР.

Посмотрим на еще один пример из запроса, где также необходимо приведение типа для КПП:


ВЫРАЗИТЬ(ВЫБОР
    КОГДА КорректировкаРеализации.Номенклатура.ВестиУчетПоСериям
        ТОГДА КорректировкаРеализации.Номенклатура.Производитель.КПП
    ИНАЧЕ КорректировкаРеализации.Номенклатура.ПроизводительЕГАИС.КПП
КОНЕЦ КАК СТРОКА(9)) КАК ВозвратКПППроизводителя

Здесь мы видим аналогичную ситуацию: КПП имеет длину 9 символов. Явное указание СТРОКА(9) гарантирует, что СКД не будет пытаться оптимизировать это поле и выведет его корректно для всех строк, независимо от того, из какой таблицы (основной или ЕГАИС) пришло значение.

Подведем итоги и дадим рекомендации

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

Таким образом, мы рассмотрели проблему исчезновения данных в СКД и выяснили, что явная типизация — это лучший инструмент разработчика для создания надежных и отказоустойчивых отчетов.

← На главную