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