Как лучше сделать сравнение показателей текущего и прошлого периодов в СКД без дублирования запросов?

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

Разработка отчетов со сравнением показателей за разные периоды (например, текущий месяц к аналогичному месяцу прошлого года или текущий квартал к предыдущему) — одна из наиболее частых задач при построении аналитики. Зачастую разработчики идут по пути наименьшего сопротивления: дублируют запросы в схеме компоновки данных (СКД), объединяют их вручную или, что еще хуже, программно соединяют два разных табличных документа в коде формы. Все эти подходы приводят к усложнению поддержки отчета: любое изменение в структуре данных требует двойной работы.

В этой статье мы подробно разберем, как элегантно решить задачу сравнения периодов в СКД стандартными средствами платформы 1С. Мы рассмотрим 4 эффективных метода, которые позволят вам избежать дублирования кода и сделать отчет гибким и простым в обслуживании.


Метод 1. Использование встроенной функции СКД «ВычислитьВыражение» (Рекомендуемый)

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

Суть метода: Мы пишем один простой запрос, который выбирает данные за весь диапазон (включающий и текущий, и прошлый периоды). Всю дальнейшую работу по группировке и расчету отклонений мы перекладываем на саму систему компоновки данных.

Рассмотрим по шагам, как это настроить:

  1. Создайте набор данных - запрос, который выбирает показатели с детализацией по периоду (например, по месяцам):
    
    ВЫБРАТЬ
        ПродажиОбороты.Номенклатура КАК Номенклатура,
        ПродажиОбороты.Период КАК Период,
        ПродажиОбороты.СуммаОборот КАК СуммаПродаж
    ИЗ
        РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Месяц, ) КАК ПродажиОбороты
    
  2. Перейдите на вкладку «Ресурсы». Добавьте стандартный ресурс СуммаПродаж с выражением Сумма(СуммаПродаж).
  3. Теперь создадим ресурс для вывода показателя прошлого периода. Назовем его, например, СуммаПродажПрошлыйПериод. В поле «Выражение» запишем следующую конструкцию: ВычислитьВыражение("Сумма(СуммаПродаж)", "Период", , "Предыдущая", "Предыдущая") Эта формула указывает СКД взять значение ресурса Сумма(СуммаПродаж) из предыдущей колонки группировки по полю Период.
  4. Для расчета абсолютного отклонения (дельты) создадим еще один ресурс ОтклонениеСуммы и пропишем для него простую формулу:
    
    Сумма(СуммаПродаж) - ВычислитьВыражение("Сумма(СуммаПродаж)", "Период", , "Предыдущая", "Предыдущая")
    
  5. В настройках структуры отчета выведите таблицу: в строках укажите поле Номенклатура, а в колонках — Период.

Преимущества метода: Запрос остается максимально простым и быстрым, формулы пишутся на уровне настроек ресурсов СКД и легко читаются, а расчет дельты происходит автоматически на лету.


Метод 2. Связи наборов данных со сдвигом параметров

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

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

Рассмотрим алгоритм настройки:

  1. Создайте НаборДанныхТекущий (запрос к регистру продаж за текущий период с параметрами &НачалоПериода и &КонецПериода).
  2. Создайте второй набор данных НаборДанныхПрошлый. Это может быть копия первого запроса, но параметры в нем назовем иначе: &НачалоПериодаПрошлый и &КонецПериодаПрошлый.
  3. Перейдите на вкладку «Связи наборов данных». Добавьте новую строку связи:
    • Источник связи: НаборДанныхТекущий
    • Приемник связи: НаборДанныхПрошлый
    • Условие связи: Номенклатура = Номенклатура (и другие необходимые аналитики)
  4. В этой же строке связи в колонке «Параметры» свяжите параметры приемника с выражениями сдвига дат:
    • Для параметра НачалоПериодаПрошлый укажите выражение: ДобавитьКДате(&НачалоПериода, "Год", -1)
    • Для параметра КонецПериодаПрошлый укажите выражение: ДобавитьКДате(&КонецПериода, "Год", -1)

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


Метод 3. Объединение периодов в одном запросе с условным разделением

Если вы хотите получить высокую производительность и полный контроль над выборкой данных без использования связей наборов данных (которые могут работать медленнее на больших объемах), можно объединить периоды непосредственно в одном SQL-запросе с использованием признака периода.

Рассмотрим структуру такого запроса:


ВЫБРАТЬ
    ПродажиОбороты.Номенклатура КАК Номенклатура,
    ПродажиОбороты.СуммаОборот КАК СуммаТекущая,
    0 КАК СуммаПрошлая
ИЗ
    РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ПродажиОбороты

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ПродажиОборотыПрошлый.Номенклатура,
    0,
    ПродажиОборотыПрошлый.СуммаОборот
ИЗ
    РегистрНакопления.Продажи.Обороты(
        ДОБАВИТЬКДАТЕ(&НачалоПериода, ГОД, -1), 
        ДОБАВИТЬКДАТЕ(&КонецПериода, ГОД, -1), , ) КАК ПродажиОборотыПрошлый

После этого на вкладке «Ресурсы» мы определяем показатели стандартным суммированием:

Важный нюанс: Обратите внимание, что функции типа ДОБАВИТЬКДАТЕ в параметрах виртуальных таблиц могут снижать производительность, если СУБД не сможет использовать индексы. Если базы данных огромные, лучше передавать рассчитанные даты через предопределенные параметры СКД (рассчитав их в модуле объекта при компоновке результата отчета).


Метод 4. Динамическая таблица периодов (ВТ_Периоды) для произвольного сравнения

Иногда перед разработчиком встает задача дать пользователю возможность сравнивать не просто "этот год и прошлый", а любые произвольные периоды, которые пользователь сам выбирает в табличной части на форме отчета (например, сравнить продажи во время акции "Черная пятница" с обычным периодом продаж).

В этом случае классические методы с жестко прописанными сдвигами дат не сработают. Нам поможет передача внешней таблицы периодов.

Проанализируем пошагово реализацию этого механизма:

  1. Создаем структуру (или временную таблицу в запросе через менеджер временных таблиц), содержащую колонки: ИмяПериода, ДатаНачала, ДатаОкончания.
  2. В основном запросе СКД делаем соединение нашей таблицы продаж с этой таблицей периодов:
    
    ВЫБРАТЬ
        ВТ_Периоды.ИмяПериода КАК ИмяПериода,
        ПродажиОбороты.Номенклатура КАК Номенклатура,
        ПродажиОбороты.СуммаОборот КАК СуммаПродаж
    ИЗ
        ВТ_Периоды КАК ВТ_Периоды
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты(,, День, ) КАК ПродажиОбороты
            ПО ПродажиОбороты.Период МЕЖДУ ВТ_Периоды.ДатаНачала И ВТ_Периоды.ДатаОкончания
    
  3. В настройках отчета выводим таблицу, где группировкой колонок будет выступать поле ИмяПериода.

При таком подходе отчет становится абсолютно универсальным. Сколько бы периодов ни выбрал пользователь на форме, СКД автоматически выведет соответствующее количество колонок для сравнения, а расчет итогов и дельты можно настроить через ресурсы с помощью тех же выражений, что мы рассматривали в Меоде 1.


Резюме

Каждый из рассмотренных методов имеет свою область применения:

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

← На главную