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

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

Сравнение показателей текущего периода с аналогичным периодом прошлого года (анализ Year-over-Year) — одна из наиболее востребованных задач в управленческом учете и торговой аналитике. Несмотря на кажущуюся простоту реализации в табличных редакторах, в 1С эта задача требует понимания работы механизмов компоновки данных и построения запросов. В данной статье мы разберем, как объединить данные из разных временных отрезков в одну структуру и корректно сопоставить их по неделям.

Механика объединения данных в одном запросе

Для того чтобы вывести данные за два разных периода в одной строке, разделенной по колонкам, мы не можем просто выбрать данные из базы. Нам необходимо применить механизм ОБЪЕДИНИТЬ ВСЕ (UNION ALL) в тексте запроса. Основная идея заключается в том, чтобы привести данные за прошлый год и текущий год к единому набору полей, где показатели будут разнесены по разным ресурсам.

Рассмотрим примерную структуру запроса. Мы создаем две выборки: одна для текущего года, вторая — для прошлого. В каждой выборке мы создаем колонки для обоих показателей, но заполняем их выборочно.


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

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

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

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

Тонкости группировки по номеру недели

Использование встроенной функции НЕДЕЛЯ() в языке запросов 1С — самый быстрый способ получить номер недели от начала года. Однако здесь кроется важный нюанс: вычисление номера недели зависит от региональных настроек сервера и того, на какой день недели пришлось 1 января. Выясним причину возможного рассогласования: если в текущем году 1 января — это понедельник, а в прошлом — четверг, порядковые номера недель могут сместиться относительно рабочих дней.

Для более точного сопоставления профессионалы рекомендуют использовать приведение всех дат к началу недели через функцию НАЧАЛОПЕРИОДА(Дата, НЕДЕЛЯ) или использовать специализированные производственные календари. Если же допустима стандартная логика 1С, то группировка по номеру недели будет выглядеть так:


ВЫБРАТЬ
    Т.НомерНедели КАК Неделя,
    СУММА(Т.СуммаТекущийГод) КАК СуммаТекущая,
    СУММА(Т.СуммаПрошлыйГод) КАК СуммаПрошлая
ИЗ
    (ВложенныйЗапросСОбъединением) КАК Т
СГРУППИРОВАТЬ ПО
    Т.НомерНедели

Реализация через Систему компоновки данных (СКД)

Если мы используем СКД, задачу можно решить еще элегантнее. Рассмотрим метод «смещения периода». Мы можем в наборе данных для прошлого года виртуально «прибавить» один год к дате продажи, чтобы система считала, что эти данные относятся к тому же временному интервалу, что и текущие продажи. Это позволит СКД автоматически соединить записи по полю Период.

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

  1. Добавим группировку типа "Таблица".
  2. В Строки таблицы добавим поле НомерНедели.
  3. В Колонки можно добавить поле Период или оставить их статичными, если мы выводим показатели «Текущий» и «Прошлый» как отдельные ресурсы.
  4. В Ресурсы добавим СуммаТекущая и СуммаПрошлая.

Обработка проблемы 53-й недели

Разберем ситуацию, когда в одном году 52 недели, а в другом — 53. Это происходит из-за особенностей календаря. Если просто сопоставлять данные по номеру недели, то 53-я неделя текущего года останется без пары из прошлого года. Чтобы отчет не выглядел «рваным», можно использовать алгоритмы сглаживания или привязывать данные к «ретейл-календарю» (4-4-5), где количество недель в месяцах и годах строго фиксировано. В простых случаях достаточно функции ЕСТЬNULL(), чтобы вместо пустых значений на 53-й неделе выводился ноль.

Оптимизация производительности с помощью временных таблиц

Когда данных в регистрах очень много, прямое объединение в одном запросе может привести к замедлению работы. Посмотрим на пример оптимизации через временные таблицы:

  1. Сначала выберем данные за текущий период во временную таблицу ВТ_ТекущиеДанные.
  2. Затем выберем данные за прошлый период во временную таблицу ВТ_ПрошлыеДанные.
  3. Проиндексируем обе таблицы по полю НомерНедели.
  4. Выполним итоговое соединение или объединение этих таблиц.

Такой подход позволяет СУБД быстрее обрабатывать индексы и сокращает время ожидания формирования отчета пользователем.

Расчет отклонений (Δ)

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

Важно помнить о защите от деления на ноль. Используем следующую формулу:

(ЕСТЬNULL(СуммаТекущая, 0) - ЕСТЬNULL(СуммаПрошлая, 0)) / ВЫБОР КОГДА ЕСТЬNULL(СуммаПрошлая, 0) = 0 ТОГДА 1 ИНАЧЕ СуммаПрошлая КОНЕЦ * 100

Это обеспечит корректное отображение данных, даже если в прошлом году продаж в эту конкретную неделю не было вовсе.

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

← На главную