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