Почему в отчете СКД не выводится описание номенклатуры и как это исправить?

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

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

Проанализируем исходную проблему. Разработчик создал запрос для прайс-листа, который должен выводить номенклатуру, ее изображение, цену, остаток и описание. Но поле «Описание» появляется не во всех строках отчета.

Вот пример запроса, который приводил к такому поведению:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.ФайлКартинки КАК ФайлКартинки,
    Номенклатура.ФайлОписанияДляСайта КАК ФайлОписанияДляСайта,
    Номенклатура.НаборУпаковок КАК НаборУпаковок,
    Номенклатура.Описание КАК Описание
ПОМЕСТИТЬ ВТНоменклатура
ИЗ
    Справочник.Номенклатура КАК Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ЦеныНоменклатурыСрезПоследних.ВидЦены КАК ВидЦены,
    СУММА(ЦеныНоменклатурыСрезПоследних.Цена) КАК Цена,
    ВТНоменклатура.Ссылка КАК Ссылка,
    ТоварыНаСкладахОстатки.ВНаличииОстаток КАК ВНаличииОстаток,
    ВТНоменклатура.ФайлКартинки КАК Изображение,
    ВТНоменклатура.ФайлОписанияДляСайта КАК ОписаниеДляПрайса,
    ВТНоменклатура.НаборУпаковок КАК НаборУпаковок,
    ВложенныйЗапрос.Ссылка КАК Ссылка1,
    ВТНоменклатура.Описание КАК Описание
ИЗ
    ВТНоменклатура КАК ВТНоменклатура
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаЦен, ) КАК ЦеныНоменклатурыСрезПоследних
        ПО ВТНоменклатура.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаЦен, ) КАК ТоварыНаСкладахОстатки
        ПО ВТНоменклатура.Ссылка = ТоварыНаСкладахОстатки.Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
            УпаковкиЕдиницыИзмерения.Ссылка КАК Ссылка,
            УпаковкиЕдиницыИзмерения.Владелец КАК Владелец
        ИЗ
            Справочник.УпаковкиЕдиницыИзмерения КАК УпаковкиЕдиницыИзмерения
        ГДЕ
            УпаковкиЕдиницыИзмерения.ПометкаУдаления = ЛОЖЬ) КАК ВложенныйЗапрос
        ПО ВТНоменклатура.Ссылка = ВложенныйЗапрос.Владелец
СГРУППИРОВАТЬ ПО
    ВТНоменклатура.Ссылка,
    ЦеныНоменклатурыСрезПоследних.ВидЦены,
    ТоварыНаСкладахОстатки.ВНаличииОстаток,
    ВТНоменклатура.ФайлКартинки,
    ВТНоменклатура.ФайлОписанияДляСайта,
    ВТНоменклатура.НаборУпаковок,
    ВложенныйЗапрос.Ссылка,
    ВТНоменклатура.Описание

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

Причина №1: Группировка по полям неограниченной длины

Самая вероятная и фундаментальная причина проблемы — это попытка сгруппировать данные по полю ВТНоменклатура.Описание. В большинстве конфигураций 1С реквизит «Описание» у справочника «Номенклатура» имеет тип Строка неограниченной длины.

Техническое ограничение платформы 1С и СУБД заключается в том, что группировка по полям неограниченной длины (в базах данных MS SQL это типы `NTEXT`, `NVARCHAR(MAX)` и т.п.) невозможна или работает некорректно. Система управления базами данных не может эффективно сравнивать и объединять строки потенциально огромного размера. Когда 1С встречает такую конструкцию в запросе, результат может быть непредсказуемым: либо возникнет ошибка, либо, как в нашем случае, значения этих полей могут просто «потеряться» в итоговой выборке.

В данном запросе поле Описание включено в секцию СГРУППИРОВАТЬ ПО, что и является корнем зла. Система пытается сгруппировать записи, но из-за ограничений на строковые поля неограниченной длины, значения для некоторых строк не подтягиваются.

Причина №2: Избыточная и нелогичная структура запроса

Помимо основной проблемы, сам запрос построен неоптимально для задач СКД.

  1. Избыточные поля в группировке. В секцию СГРУППИРОВАТЬ ПО включено огромное количество полей, включая файлы картинок и описаний. Это делает запрос тяжелым и усложняет его анализ.
  2. Нелогичное суммирование цены. В запросе используется агрегатная функция СУММА(ЦеныНоменклатурыСрезПоследних.Цена). Однако данные получаются из виртуальной таблицы СрезПоследних, которая для каждой номенклатуры и вида цены вернет только одну актуальную запись. Суммировать здесь нечего. Если из-за других соединений (например, с упаковками) строки дублируются, то суммирование цены приведет к некорректному результату (завышенной цене). Это явная логическая ошибка.
  3. Предварительное помещение всех реквизитов во временную таблицу. Запрос сначала помещает множество реквизитов номенклатуры во временную таблицу ВТНоменклатура, а затем соединяет ее с другими таблицами. Это лишний шаг, который усложняет и замедляет выполнение.

Решение: как правильно построить запрос для СКД

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

Разберем по шагам, как переделать запрос.

Шаг 1. Упрощаем набор данных в запросе

Основная задача запроса — получить ключевые сущности: ссылку на номенклатуру, ее цену и остаток. Все остальные данные (описание, артикул, картинка) СКД сможет получить сама, используя ссылку.

Для большей надежности и производительности лучше получать цены и остатки в отдельных временных таблицах, а затем соединять их с основной таблицей номенклатуры. Это позволяет избежать дублирования строк, если у товара несколько цен или он лежит на нескольких складах (в зависимости от условий отбора).

Вот как может выглядеть более правильный и оптимизированный запрос:


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

Обратите внимание:

Шаг 2. Добавляем реквизиты в настройках СКД

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

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

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

Итог

Чтобы избежать проблем с выводом данных в отчетах на СКД, особенно с полями неограниченной длины, следуйте двум простым правилам:

  1. Не группируйте данные по полям неограниченной длины. Это техническое ограничение, которое необходимо учитывать.
  2. Используйте всю мощь СКД. Составляйте в конструкторе запросов максимально простой набор данных, содержащий ссылки на основные объекты (справочники, документы). Все связанные с ними реквизиты добавляйте уже в настройках отчета через точку.

Такой подход не только решает проблему с пропадающими значениями, но и делает ваши отчеты более гибкими, быстрыми и простыми в поддержке.

← На главную