В практике разработки отчетов на системе компоновки данных (СКД) часто возникает задача разделения одного потока данных на несколько визуальных таблиц с разной логикой обработки. Рассмотрим классическую ситуацию: у нас есть сырье, которое делится на две категории — со сроком годности и без него. Для первой категории необходимо выполнить пересчет всех остатков в килограммы, используя коэффициенты упаковок, а для второй — оставить данные «как есть». При этом в итоге нужно получить не один общий список, а две отдельные таблицы в одном отчете.
В этой статье мы подробно разберем, как спроектировать такой отчет, начиная от структуры запроса и заканчивая настройками компоновки данных, чтобы избежать типичных ошибок вроде «раздувания» итогов или некорректного вывода данных.
Самая распространенная ошибка новичков — попытка решить задачу вывода двух таблиц исключительно внутри текста запроса с помощью оператора ОБЪЕДИНИТЬ. Хотя это технически возможно, такой подход усложняет поддержку отчета. На самом деле СКД позволяет вывести сколько угодно таблиц на основе одного и того же набора данных.
Разберем алгоритм настройки:
Номенклатура.СрокГодности ЕСТЬ НЕ NULL (или по признаку «Вид номенклатуры»).Номенклатура.СрокГодности ЕСТЬ NULL.Таким образом, мы используем один запрос, но фильтруем данные на уровне вывода, что позволяет легко менять оформление каждой таблицы по отдельности.
Проанализируем ситуацию с пересчетом. В тексте запроса часто пишут громоздкие конструкции ВЫБОР КОГДА.... Однако гораздо удобнее вынести логику расчета в «Вычисляемые поля» СКД. Это позволит не загромождать запрос и использовать коэффициенты пересчета более гибко.
Допустим, наш запрос получает поле Количество и Коэффициент (из справочника упаковок или единиц измерения). Рассмотрим выражение для вычисляемого поля КоличествоВКГ:
Выражение:
Выбор
Когда Номенклатура.ВидНоменклатуры = &СырьеСоСроком
Тогда Количество * Коэффициент
Иначе Количество
Конец
Важно помнить, что для корректного суммирования этого поля в итогах, его нужно добавить на вкладку «Ресурсы» с функцией СУММА(КоличествоВКГ). Это гарантирует, что при группировке по складам или категориям данные будут складываться правильно, даже если коэффициенты у разных позиций отличаются.
Рассмотрим фрагмент кода, который часто приводит к ошибкам («абракадабре» в цифрах). Основная причина искажения данных в сложных отчетах — использование перечисления таблиц через запятую в блоке ИЗ, что создает декартово произведение.
Как делать нельзя:
ВЫБРАТЬ
Цены.Цена,
Остатки.Количество
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ) КАК Цены,
ВТ_Остатки КАК Остатки,
ВТ_Сырье КАК Сырье
ГДЕ
Цены.Номенклатура = Остатки.Номенклатура
Проанализируем эту ситуацию: если в таблице Сырье окажется несколько строк для одной номенклатуры (например, разные регистраторы или склады), то цена и остатки умножатся на количество этих строк. Чтобы этого избежать, всегда используем ЛЕВОЕ СОЕДИНЕНИЕ с четким указанием условий связи.
Правильный вариант построения финального запроса:
ВЫБРАТЬ
Остатки.Номенклатура КАК Сырьё,
Остатки.Склад,
Остатки.ВНаличииКонечныйОстаток КАК ОстатокБазовый,
// Применяем коэффициент сразу в запросе, если не используем вычисляемые поля
ВЫБОР
КОГДА Остатки.Номенклатура.ВестиУчетПоСрокамГодности
ТОГДА Остатки.ВНаличииКонечныйОстаток * ЕСТЬNULL(УП.Коэффициент, 1)
ИНАЧЕ Остатки.ВНаличииКонечныйОстаток
КОНЕЦ КАК ОстатокВКГ,
ЕСТЬNULL(Цены.Цена, 0) КАК Цена
ИЗ
ВТ_Остатки КАК Остатки
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Упаковки КАК УП
ПО Остатки.Номенклатура = УП.Владелец
И УП.ЕдиницаИзмерения = &ЕдиницаКГ
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&КонецПериода, ) КАК Цены
ПО Остатки.Номенклатура = Цены.Номенклатура
Если в вашей конфигурации (например, УТ 11 или ERP) коэффициенты хранятся в разных местах (базовая единица, единицы для отчетов, упаковки), выясним причину возможных расхождений. Рекомендуется сначала собрать все нужные коэффициенты во временную таблицу ВТ_Коэффициенты, проиндексировать ее по полю Номенклатура, а уже затем соединять с основными остатками.
Посмотрим на пример подготовки такой таблицы:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Номенклатура,
ВЫБОР
КОГДА Номенклатура.ЕдиницаИзмерения = &КГ ТОГДА 1
ИНАЧЕ Упаковки.Коэффициент
КОНЕЦ КАК Коэффициент
ПОМЕСТИТЬ ВТ_Коэффициенты
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.УпаковкиНоменклатуры КАК Упаковки
ПО Номенклатура.Ссылка = Упаковки.Владелец
И Упаковки.ЕдиницаИзмерения = &КГ
ИНДЕКСИРОВАТЬ ПО
Номенклатура
;
Важный нюанс: использование ИНДЕКСИРОВАТЬ ПО значительно ускоряет работу отчета на больших объемах данных. Без индекса временной таблицы соединение при расчете итогов может занимать в несколько раз больше времени.
Если задача подразумевает проверку срока годности не просто как «признака» в карточке номенклатуры, а как конкретной даты, данные необходимо извлекать из регистра накопления в разрезе Серий.
В этом случае структура запроса изменится:
ОстаткиИОбороты обязательно указываем Серия.Серия.СрокГодности.Такой подход позволит сделать отчет максимально точным и избежать ситуации, когда одна и та же номенклатура из разных партий попадает не в ту таблицу.
Для реализации задачи по выводу двух таблиц с разной логикой пересчета в СКД, мы рекомендуем совмещать мощь языка запросов и гибкость настроек компоновщика. Используйте временные таблицы с индексами для подготовки данных, ЛЕВОЕ СОЕДИНЕНИЕ для исключения дублей, и разделяйте визуализацию в настройках структуры отчета. Это сделает вашу разработку профессиональной, быстрой и понятной для конечного пользователя.