Как в запросе 1С распределить данные по месяцам в виде шахматки

Программист IT и автоматизация бизнеса
← На главную

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

Вариант 1. Разворот данных через конструкцию ВЫБОР КОГДА в тексте запроса

Если количество периодов строго ограничено и заранее известно (например, классический календарный год из 12 месяцев), задачу можно решить чисто средствами языка запросов 1С. Для этого используется условная конструкция ВЫБОР КОГДА в сочетании с агрегатной функцией СУММА и группировкой.

Рассмотрим пример, в котором требуется получить количество заказов по товарам с разбивкой по четырем месяцам. Сначала подготовим временную таблицу с номером месяца, а затем выполним агрегацию по каждой колонке:


ВЫБРАТЬ
    МЕСЯЦ(ЗаказыПоставщикам.Период) КАК НомерМесяца,
    ЗаказыПоставщикам.Номенклатура КАК Номенклатура,
    ЗаказыПоставщикам.Количество КАК Количество
ПОМЕСТИТЬ ВТ_Данные
ИЗ
    РегистрНакопления.ЗаказыПоставщикам КАК ЗаказыПоставщикам
ГДЕ
    ЗаказыПоставщикам.Период МЕЖДУ &ДатаНачала И &ДатаОкончания
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Данные.Номенклатура КАК Номенклатура,
    СУММА(ВЫБОР КОГДА ВТ_Данные.НомерМесяца = 1 ТОГДА ВТ_Данные.Количество ИНАЧЕ 0 КОНЕЦ) КАК Январь,
    СУММА(ВЫБОР КОГДА ВТ_Данные.НомерМесяца = 2 ТОГДА ВТ_Данные.Количество ИНАЧЕ 0 КОНЕЦ) КАК Февраль,
    СУММА(ВЫБОР КОГДА ВТ_Данные.НомерМесяца = 3 ТОГДА ВТ_Данные.Количество ИНАЧЕ 0 КОНЕЦ) КАК Март,
    СУММА(ВЫБОР КОГДА ВТ_Данные.НомерМесяца = 4 ТОГДА ВТ_Данные.Количество ИНАЧЕ 0 КОНЕЦ) КАК Апрель
ИЗ
    ВТ_Данные КАК ВТ_Данные
СГРУППИРОВАТЬ ПО
    ВТ_Данные.Номенклатура

Проанализируем важные нюансы и ограничения данного метода:

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

Вариант 2. Построение кросс-таблицы в Системе компоновки данных (СКД)

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

Разберем по шагам, как настроить такой отчет:

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

Вариант 3. Использование Построителя отчета (ПостроительОтчета)

В типовых конфигурациях на обычных формах (включая конфигурации на платформе 8.1 и 8.2) альтернативой СКД выступает объект ПостроительОтчета. Он позволяет сформировать кросс-таблицу программно через измерения строк и колонок.

Посмотрим на пример программной инициализации построителя:


Построитель = Новый ПостроительОтчета;
Построитель.Текст = 
    "ВЫБРАТЬ
    |	Заказы.Номенклатура КАК Номенклатура,
    |	НАЧАЛОПЕРИОДА(Заказы.Период, МЕСЯЦ) КАК ПериодМесяц,
    |	Заказы.Количество КАК Количество
    |ИЗ
    |	РегистрНакопления.ЗаказыПоставщикам КАК Заказы
    |ИТОГИ
    |	СУММА(Количество)
    |ПО
    |	Номенклатура,
    |	ПериодМесяц";

Построитель.ЗаполнитьНастройки();

// Назначаем строки и колонки
Построитель.ИзмеренияСтроки.Добавить("Номенклатура");
Построитель.ИзмеренияКолонки.Добавить("ПериодМесяц");

// Выводим результат в табличный документ
ТабДок = Новый ТабличныйДокумент;
Построитель.Вывести(ТабДок);
ТабДок.Показать();

Вариант 4. Программный разворот в ТаблицуЗначений

Когда результат разворота требуется не для показа пользователю в отчете, а для дальнейших программных алгоритмов или выгрузок, шахматку формируют в объекте ТаблицаЗначений:

  1. Выполняем запрос для получения списка уникальных периодов за выбранный интервал.
  2. Создаем пустую таблицу значений и программно добавляем колонку измерения (например, Номенклатура), а затем в цикле через метод ТаблицаЗначений.Колонки.Добавить() создаем колонки под каждый полученный месяц.
  3. Выбираем детальные записи запросом (товар, месяц, значение) и заполняем подготовленную таблицу, находя нужную строку по номенклатуре и присваивая значение в динамически созданную колонку соответствующего месяца.

Резюме: для разовых задач с фиксированным числом колонок допустимо использовать запрос с ВЫБОР КОГДА. Однако для построения полноценных пользовательских отчетов стандартом является СКД, которая автоматически масштабирует количество колонок, обеспечивает правильную хронологическую сортировку и заполняет пропущенные периоды без усложнения исходного кода.

← На главную