При разработке аналитических отчетов в системе 1С:Предприятие 8, особенно в таких комплексных конфигурациях, как Управление производственным предприятием (УПП) 1.3, разработчики часто сталкиваются с необходимостью сравнения показателей за разные периоды. Типовой отчет "Валовая прибыль" в УПП достаточно сложен, содержит множество временных таблиц и вложенных запросов. Попытка просто продублировать этот запрос дважды (для основного и сравниваемого периодов) приводит к избыточности кода, снижению производительности и трудностям при поддержке.
В этой статье мы разберем, как реализовать сравнение периодов максимально эффективно, используя возможности Системы компоновки данных (СКД). Мы проанализируем несколько подходов: от простых вычисляемых полей до использования продвинутых функций агрегации.
Это самый доступный способ, который обсуждался на форуме. Суть заключается в том, чтобы не менять структуру запроса кардинально, а расширить его период охвата и разделить данные на уровне логики СКД. Разберем этот процесс по шагам.
Во-первых, нам необходимо изменить параметры запроса. Вместо двух жестких пар дат (Начало1-Конец1 и Начало2-Конец2), мы настраиваем запрос таким образом, чтобы он выбирал данные за один общий период, включающий в себя обе сравниваемые границы. В секции ГДЕ основного запроса условие должно выглядеть примерно так:
ГДЕ
Продажи.Период МЕЖДУ &НачалоОбщее И &КонецОбщее
Во-вторых, на закладке "Вычисляемые поля" в СКД мы создаем отдельные поля для каждого периода. Например, для выручки это будет выглядеть следующим образом:
Создаем поле ВыручкаПериод1. В выражении пишем:
ВЫБОР
КОГДА Период МЕЖДУ &Начало1 И &Конец1
ТОГДА Выручка
ИНАЧЕ 0
КОНЕЦ
Аналогично создаем поле ВыручкаПериод2:
ВЫБОР
КОГДА Период МЕЖДУ &Начало2 И &Конец2
ТОГДА Выручка
ИНАЧЕ 0
КОНЕЦ
В-третьих, крайне важно правильно настроить Ресурсы. Чтобы данные корректно суммировались по группировкам (Номенклатура, Контрагент), в поле "Выражение" на закладке ресурсы указываем: СУММА(ВыручкаПериод1) и СУММА(ВыручкаПериод2).
Если периодов для сравнения больше двух или вы хотите сделать отчет более гибким, мы можем использовать механизм "виртуального измерения". Рассмотрим, как это упрощает структуру колонок.
В тексте запроса мы добавляем вычисляемое поле, которое помечает каждую запись идентификатором периода:
ВЫБОР
КОГДА Продажи.Период МЕЖДУ &Начало1 И &Конец1 ТОГДА "Период 1"
КОГДА Продажи.Период МЕЖДУ &Начало2 И &Конец2 ТОГДА "Период 2"
ИНАЧЕ "Вне периода"
КОНЕЦ КАК НомерПериода
В настройках СКД на закладке "Настройки" мы добавляем это поле НомерПериода в колонки таблицы. В строки добавляем нужную нам аналитику (например, Номенклатура). В выбранные поля добавляем Выручка, Себестоимость и ВаловаяПрибыль. СКД автоматически разнесет данные по столбцам, и вам не придется создавать десятки вычисляемых полей для каждого ресурса.
Этот метод считается более профессиональным, когда нужно вывести данные "прошлого года" и "текущего года" в одной строке для удобного расчета отклонений. Проанализируем, как это настроить:
НаборТекущийПериод и НаборПрошлыйПериод.&Начало1 и &Конец1, во втором — &Начало2 и &Конец2.Номенклатура, Контрагент, Склад.Преимущество этого метода в том, что вы можете легко обращаться к полям обоих наборов данных в одном вычисляемом поле для расчета разницы. Например, поле АбсолютноеОтклонение будет иметь выражение: НаборТекущийПериод.Прибыль - НаборПрошлыйПериод.Прибыль.
Если отчет строится как линейный список периодов (например, по месяцам), мы можем использовать мощную функцию СКД ВычислитьВыражение. Это позволяет сравнивать текущее значение со значением в предыдущей колонке без изменения запроса.
Пример выражения для ресурса, который считает прирост к предыдущему периоду:
Сумма(Продажи) - ВычислитьВыражение("Сумма(Продажи)", , , "Предыдущая", "Текущая")
Эта функция работает на уровне итогов и позволяет строить динамические отчеты, где сравниваемый период всегда "сдвигается" относительно текущего.
При работе с УПП 1.3 важно помнить, что данные о себестоимости зависят от используемого режима учета: РАУЗ (Расширенная аналитика учета затрат) или Партионный учет. Проанализируем влияние этого фактора на наш отчет:
Если в базе используется РАУЗ, данные о себестоимости продаж попадают в регистр Продажи только после проведения документа "Регламентная операция" с видом "Расчет себестоимости". Поэтому при сравнении периодов убедитесь, что за оба периода расчет себестоимости завершен корректно. В противном случае валовая прибыль за текущий (незакрытый) месяц будет равна выручке, что сделает сравнение бессмысленным.
Выясним причину возможных расхождений: часто пользователи сравнивают оперативные данные текущего месяца с итоговыми данными прошлого. Для корректности рекомендуем использовать в запросе временные таблицы, которые предварительно выбирают данные из регистра Продажи, а затем соединяют их с данными о дополнительных расходах, если это требуется спецификой вашего учета.
Разберем, как сделать так, чтобы тяжелый отчет не "вешал" систему. Вместо того чтобы выполнять два вложенных запроса, попробуем использовать временные таблицы следующим образом:
Продажи и ПродажиСебестоимость за максимально широкий период (от самого раннего начала до самого позднего конца).ВТ_ДанныеПродаж. Это позволит системе просканировать индексы регистров только один раз.ВТ_ДанныеПродаж, распределяя их по периодам с помощью конструкции ВЫБОР.Такой подход значительно сокращает нагрузку на сервер Microsoft SQL Server или PostgreSQL, так как основные вычисления проводятся над уже отобранным небольшим объемом данных в оперативной памяти.
Рассмотрим финальный совет: для удобства пользователя добавьте в настройки отчета "Пользовательские поля" типа "Выбор". Это позволит менеджеру самостоятельно определять, какие данные считать "планом", а какие "фактом" или "эталоном", не прибегая к помощи программиста для изменения конфигурации.