Сравнение показателей текущего периода с аналогичным периодом прошлого года — одна из самых частых задач при разработке управленческой отчетности. В Системе компоновки данных (СКД) новички часто сталкиваются с проблемой: при попытке соединить два запроса за разные годы суммы начинают «умножаться», выдавая некорректные («космические») результаты. В этой статье мы разберем, почему это происходит, и рассмотрим правильный способ реализации такого отчета.
Рассмотрим ситуацию: у нас есть данные по продажам за январь 2023 года и за январь 2024 года. Мы хотим вывести их в одну строку по конкретному менеджеру или покупателю. Если мы попытаемся использовать ЛЕВОЕ СОЕДИНЕНИЕ по полю Покупатель, 1С попытается сопоставить каждую продажу прошлого года с каждой продажей текущего года для этого контрагента. Если в прошлом году было 10 документов, а в текущем — 5, в результате соединения мы можем получить 50 строк. Именно из-за этого итоговые суммы в отчетах становятся неверными.
Проанализируем ситуацию: чтобы данные сопоставлялись корректно, нам нужно либо обеспечить уникальность записей в обеих таблицах перед соединением (например, сгруппировать их до уровня контрагента), либо использовать механизм объединения запросов.
Наиболее надежный и математически точный способ — это собрать данные за прошлый период во временную таблицу, а затем объединить их с данными текущего периода в одном наборе данных. Выясним, как это реализовать по шагам на примере регистра накопления РеализацияТМЗ.
Шаг 1. Формируем данные за прошлый период
Сначала мы выбираем данные за прошлый год и помещаем их во временную таблицу. Важно сразу подготовить поле суммы для прошлого периода.
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(РеализацияТМЗОбороты.Период, МЕСЯЦ) КАК Период,
РеализацияТМЗОбороты.ДоговорКонтрагента.Владелец.ОсновнойМенеджерПокупателя КАК Покупатель,
РеализацияТМЗОбороты.СуммаОборот КАК СуммаОборотПрошл
ПОМЕСТИТЬ ДанныеПрошлогоГода
ИЗ
РегистрНакопления.РеализацияТМЗ.Обороты({(&НачалоПериода1)}, {(&КонецПериода1)}, Регистратор, ) КАК РеализацияТМЗОбороты
;
Шаг 2. Основной запрос с объединением
Теперь мы выбираем данные текущего года и добавляем к ним данные из нашей временной таблицы. Чтобы СКД могла сопоставить данные прошлого года с текущим в одной строке (например, в кросс-таблице), мы используем функцию ДОБАВИТЬКДАТЕ, «сдвигая» даты прошлого года на один год вперед.
// Выбираем данные текущего периода
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(РеализацияТМЗОбороты.Период, МЕСЯЦ) КАК Период,
РеализацияТМЗОбороты.ДоговорКонтрагента.Владелец.ОсновнойМенеджерПокупателя КАК Покупатель,
0 КАК СуммаОборотПрошл,
РеализацияТМЗОбороты.СуммаОборот КАК СуммаОборотТек
ИЗ
РегистрНакопления.РеализацияТМЗ.Обороты(, , Регистратор, ) КАК РеализацияТМЗОбороты
ОБЪЕДИНИТЬ ВСЕ
// Примешиваем данные прошлого года, сдвигая период
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(ДанныеПрошлогоГода.Период, ГОД, 1),
ДанныеПрошлогоГода.Покупатель,
ДанныеПрошлогоГода.СуммаОборотПрошл,
0 КАК СуммаОборотТек
ИЗ
ДанныеПрошлогоГода КАК ДанныеПрошлогоГода
Разберем, что мы сделали: в первой части объединения мы создали «пустую» колонку СуммаОборотПрошл (заполнили нулем), а во второй части — «пустую» колонку СуммаОборотТек. Благодаря функции ДОБАВИТЬКДАТЕ, продажи января прошлого года теперь имеют ту же дату, что и продажи января текущего года. При выводе в отчет СКД сгруппирует их по этому виртуальному периоду в одну строку.
Рассмотрим еще один профессиональный подход. Если база данных очень большая, дважды обращаться к одному и тому же регистру может быть долго. Мы можем прочитать данные один раз за весь период (от начала прошлого года до конца текущего) и разделить их с помощью конструкции ВЫБОР.
Посмотрим на пример логики в запросе:
ВЫБРАТЬ
// Приводим все даты к текущему году для сопоставления
ВЫБОР
КОГДА РеализацияТМЗОбороты.Период < &НачалоТекущегоПериода
ТОГДА ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(РеализацияТМЗОбороты.Период, МЕСЯЦ), ГОД, 1)
ИНАЧЕ НАЧАЛОПЕРИОДА(РеализацияТМЗОбороты.Период, МЕСЯЦ)
КОНЕЦ КАК ПериодДляСравнения,
Покупатель,
// Суммируем в разные колонки в зависимости от года
ВЫБОР
КОГДА РеализацияТМЗОбороты.Период < &НачалоТекущегоПериода ТОГДА СуммаОборот ИНАЧЕ 0
КОНЕЦ КАК СуммаПрошлыйГод,
ВЫБОР
КОГДА РеализацияТМЗОбороты.Период >= &НачалоТекущегоПериода ТОГДА СуммаОборот ИНАЧЕ 0
КОНЕЦ КАК СуммаТекущийГод
ИЗ
РегистрНакопления.РеализацияТМЗ.Обороты(&НачалоПрошлогоГода, &КонецТекущегоГода, , )
Чтобы отчет работал безупречно, обратим внимание на следующие настройки компоновки:
Период в схеме компоновки данных обязательно укажите роль «Период». Это позволит СКД корректно обрабатывать временные интервалы.(Сумма(СуммаОборотТек) - Сумма(СуммаОборотПрошл)) / Сумма(СуммаОборотПрошл) * 100.Проанализировав эти методы, можно сделать вывод, что использование ОБЪЕДИНИТЬ ВСЕ является наиболее прозрачным и простым способом для сравнения периодов «год к году». Это гарантирует отсутствие дублей и позволяет легко выводить данные в кросс-таблицы, где колонками будут выступать месяцы, а внутри каждой ячейки — показатели двух разных лет.