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

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

При разработке отчетов на Системе компоновки данных (СКД) часто возникает специфическая задача агрегации. Представим ситуацию: у нас есть иерархия группировок ТМЦ — Назначение — Изделие — Период. На уровне Изделия нам необходимо видеть только количество из последней временной записи (последний срез по периоду), но на уровнях Назначение и ТМЦ эти «последние» значения должны не выбираться по максимуму, а суммироваться между собой. Для схожих задач отбора записей в группировках можно использовать пример получения среза последних N записей в СКД.

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

Способ 1. Использование функции ВычислитьВыражениеСГруппировкойМассив

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

Проанализируем алгоритм настройки ресурсов:

  1. Перейдем на закладку Ресурсы в схеме компоновки данных.
  2. Добавим поле Количество и в колонке Рассчитывать по... укажем группировку Изделие. Для этого уровня мы будем использовать выражение, которое находит последнюю запись в периоде: ВычислитьВыражение("Сумма(Количество)", "Период", , "Последняя", "Последняя") Это выражение говорит системе: «Возьми сумму количества только для последней записи внутри текущего контекста периода».
  3. Теперь добавим это же поле Количество второй раз, но в колонке Рассчитывать по... укажем вышестоящие группировки: Назначение, ТМЦ и Общий итог. Выражение будет более сложным:
    
    Сумма(ВычислитьВыражениеСГруппировкойМассив("ВычислитьВыражение(""Сумма(Количество)"", ""Период"", , ""Последняя"", ""Последняя"")", "Изделие"))
    
    Разберем, как это работает: внутренняя часть берет последние значения по периодам для каждого изделия, ВычислитьВыражениеСГруппировкойМассив собирает их в виртуальный массив, а внешняя функция Сумма() складывает элементы этого массива.

Важный нюанс: Чтобы функции работы с периодами (такие как "Последняя") отрабатывали корректно, убедитесь, что в наборе данных для поля Период установлена соответствующая роль (Период, порядковый номер) и данные в отчете отсортированы по дате.

Способ 2. Оптимизация через запрос (флаг последней записи)

Если отчет строится по очень большому объему данных, использование тяжелых функций ВычислитьВыражение может замедлить формирование. В таком случае эффективнее подготовить данные еще на уровне SQL-запроса. Мы пометим каждую запись флагом, является ли она последней для конкретного изделия.

Рассмотрим, как это реализовать с помощью вложенного запроса:

Сначала найдем максимальные даты для каждой комбинации ТМЦ, Назначения и Изделия во временной таблице:


ВЫБРАТЬ
    ТМЦ,
    Назначение,
    Изделие,
    МАКСИМУМ(Период) КАК МаксПериод
ПОМЕСТИТЬ ВТ_ПоследниеДаты
ИЗ
    РегистрДанных
СГРУППИРОВАТЬ ПО
    ТМЦ, Назначение, Изделие
;

Затем соединим основную таблицу с этой временной таблицей и добавим логическое поле:


ВЫБРАТЬ
    ОсновнаяТаблица.*,
    ВЫБОР 
        КОГДА ВТ_ПоследниеДаты.МаксПериод ЕСТЬ НЕ NULL ТОГДА ИСТИНА 
        ИНАЧЕ ЛОЖЬ 
    КОНЕЦ КАК ЭтоПоследняяЗапись
ИЗ
    РегистрДанных КАК ОсновнаяТаблица
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ПоследниеДаты КАК ВТ_ПоследниеДаты
    ПО ОсновнаяТаблица.ТМЦ = ВТ_ПоследниеДаты.ТМЦ
    И ОсновнаяТаблица.Назначение = ВТ_ПоследниеДаты.Назначение
    И ОсновнаяТаблица.Изделие = ВТ_ПоследниеДаты.Изделие
    И ОсновнаяТаблица.Период = ВТ_ПоследниеДаты.МаксПериод

После этого в настройках СКД на вкладке Ресурсы выражение для поля Количество станет максимально простым и будет одинаковым для всех уровней группировок:

Сумма(Выбор Когда ЭтоПоследняяЗапись Тогда Количество Иначе 0 Конец)

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

Способ 3. Использование оконных функций (для современных платформ)

Если вы работаете на платформе 1С:Предприятие 8.3.15 и выше, мы можем применить оконные функции прямо в тексте запроса. Это избавит нас от необходимости создавать временные таблицы и соединения.

Выясним, как пронумеровать записи внутри каждой группы:


ВЫБРАТЬ
    ТМЦ,
    Назначение,
    Изделие,
    Период,
    Количество,
    НОМЕР_СТРОКИ() Над (РАЗДЕЛИТЬ ПО ТМЦ, Назначение, Изделие УПОРЯДОЧИТЬ ПО Период УБЫВ) КАК ИндексАктуальности
ИЗ
    РегистрДанных

В данном случае запись с ИндексАктуальности = 1 будет являться самой свежей для каждого изделия. В ресурсах СКД мы напишем:

Сумма(Выбор Когда ИндексАктуальности = 1 Тогда Количество Иначе 0 Конец)

Подведем итоги

Мы рассмотрели три принципиально разных подхода к решению задачи «суммы последних». Выбор конкретного метода зависит от ваших условий:

Используя эти техники, вы сможете строить сложные аналитические отчеты в СКД, которые корректно отражают динамику изменений в иерархических структурах данных.

← На главную