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

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

При разработке отчетов на Системе компоновки данных (СКД) часто возникает бизнес-задача: сравнить показатели за текущий период (например, выбранный пользователем месяц) с показателями за "все время" или за аналогичный период прошлого года. Стандартные механизмы СКД автоматически подставляют параметры &НачалоПериода и &КонецПериода во все виртуальные таблицы, что мешает получить данные за разные временные отрезки в рамках одного набора данных.

Разберем несколько эффективных способов решения этой задачи, проанализируем их плюсы и минусы, а также посмотрим на практические примеры кода.

Метод 1: Использование расширения языка запросов (фигурные скобки)

Этот метод считается наиболее "правильным" с точки зрения архитектуры СКД. Мы используем специальные конструкции в фигурных скобках {}, которые позволяют системе гибко управлять параметрами виртуальных таблиц. Посмотрим, как это реализовать в тексте запроса.

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


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

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

ВЫБРАТЬ
    ЗакупкиОборотыВесь.Номенклатура,
    0,
    ЗакупкиОборотыВесь.СтоимостьОборот
ИЗ
    РегистрНакопления.Закупки.Обороты({(&НачалоПериода2)}, {(&КонецПериода2)}, , ) КАК ЗакупкиОборотыВесь

В чем секрет этого метода? Когда мы пишем {(&НачалоПериода2)}, СКД понимает, что это необязательный параметр, который не будет конфликтовать со стандартным периодом отчета. Если в настройках СКД на вкладке "Параметры" мы оставим &НачалоПериода2 пустым, запрос за "весь период" отработает с начала времен. Если же нужно ограничить его, мы можем программно или через настройки пользователя передать туда значение.

Метод 2: Соединение через временные таблицы

Если логика отчета сложная и включает данные из разных регистров, удобнее использовать временные таблицы. Это позволяет четко разделить выборку за текущий период и выборку за "исторический" период. Проанализируем пример, где мы сначала собираем данные во временные таблицы ВТЗакупки (за весь период) и ВТЗаказы, а затем соединяем их с основными данными.

Посмотрим на структуру такого запроса:


// Помещаем данные за дополнительный период во временную таблицу
ВЫБРАТЬ
    Закупки.ДоговорКонтрагента.Владелец КАК Контрагент,
    Закупки.Регистратор.Сделка КАК Сделка,
    Закупки.СтоимостьОборот КАК СуммаЗаВесьПериод
ПОМЕСТИТЬ ВТЗакупкиВесьПериод
ИЗ
    РегистрНакопления.Закупки.Обороты({(&НачалоПериодаВесь)}, &КонецПериода, Авто, ) КАК Закупки;

// Основной запрос с объединением и левым соединением
ВЫБРАТЬ
    ЗакупкиОбороты.ДоговорКонтрагента.Владелец КАК Контрагент,
    ЗакупкиОбороты.СтоимостьОборот КАК СуммаЗаВыбранныйПериод,
    ЗакупкиВесь.СуммаЗаВесьПериод КАК СуммаВсего
ИЗ
    РегистрНакопления.Закупки.Обороты(&НачалоПериода, &КонецПериода, Авто, ) КАК ЗакупкиОбороты
ЛЕВОЕ СОЕДИНЕНИЕ ВТЗакупкиВесьПериод КАК ЗакупкиВесь
    ПО ЗакупкиОбороты.Регистратор.Сделка = ЗакупкиВесь.Сделка

Этот подход позволяет избежать дублирования строк при объединении (UNION) и выводит данные в разные колонки одной строки, что упрощает дальнейшую работу с ресурсами в компоновке.

Метод 3: Использование нескольких наборов данных

Рассмотрим еще один мощный инструмент СКД — использование двух независимых наборов данных (Запросов) внутри одной схемы. Это решение часто оказывается более производительным и простым в отладке.

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

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

Автоматизация "Всего периода" через выражения параметров

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

  1. Перейдем на вкладку "Параметры".
  2. Найдем наш параметр &НачалоПериодаВесь.
  3. В колонке "Выражение" укажем: ДАТАВРЕМЯ(1, 1, 1). Это установит пустую дату (начало времен).
  4. Для параметра &КонецПериодаВесь можно указать выражение КонецПериода(ТекущаяДата(), "День") или привязать его к основному концу периода: &КонецПериода.
  5. Установим галочку "Ограничение доступности", чтобы скрыть эти настройки от пользователя.

Оптимизация производительности

Нужно учитывать, что получение оборотов за "весь период" (с начала ведения базы) — это ресурсозатратная операция. Если ваша база данных содержит миллионы записей, такой отчет может работать медленно. Проанализируем способы оптимизации:

Настройка вывода в отчет

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

Таким образом, комбинируя механизмы расширения языка запросов и правильную настройку параметров, мы можем создавать сложные аналитические отчеты, которые позволяют пользователю видеть динамику текущих операций на фоне общих исторических данных.

← На главную