Почему запрос в СКД не группируется по дате при использовании регистратора и как это исправить

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

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

Анализ проблемы: почему стандартное соединение таблиц может давать сбой

Рассмотрим ситуацию, с которой столкнулся автор темы. Изначально была предпринята попытка создать временную таблицу всех доступных месяцев, а затем соединить её с оборотами регистра. Проанализируем этот подход. Автор использовал конструкцию:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    НАЧАЛОПЕРИОДА(ОборотыЭкспедирования.Период, МЕСЯЦ) КАК НачалоМесяца,
    КОНЕЦПЕРИОДА(ОборотыЭкспедирования.Период, МЕСЯЦ) КАК ОкончаниеМесяца
ПОМЕСТИТЬ ТВМесяцы
ИЗ
    РегистрНакопления.ОборотыЭкспедирования КАК ОборотыЭкспедирования
;

И далее выполнялось соединение с виртуальной таблицей оборотов:


ЛЕВОЕ СОЕДИНЕНИЕ ТВМесяцы КАК ТВМесяцы
ПО (ОборотыЭкспедированияОбороты.Период МЕЖДУ ТВМесяцы.НачалоМесяца И ТВМесяцы.ОкончаниеМесяца)

Выясним причину неудачи такого метода:

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

Правильное решение: использование функции НАЧАЛОПЕРИОДА напрямую

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

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


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

В данном случае мы решаем сразу несколько задач:

Настройка СКД для корректной группировки

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

  1. Перейдем на закладку Наборы данных.
  2. Найдем наше поле ПериодМесяц.
  3. В колонке Роли нажмем на кнопку редактирования.
  4. Установим флажок Период.
  5. Важно указать уровень периода (например, 1 или 2, если у вас несколько периодов).
  6. В поле Тип периода выберем значение Дополнительный период (или укажем конкретно Месяц), если мы хотим, чтобы СКД понимала иерархию дат.

Почему это важно? Когда СКД знает, что поле является периодом, она применяет специальные алгоритмы сортировки и позволяет использовать возможности вкладки Настройки для создания иерархических группировок (Период -> Регистратор).

Решение проблемы пустых месяцев (Дополнение периодов)

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

Рассмотрим, как вывести пустые месяцы без усложнения запроса:

В этом случае система сама сгенерирует недостающие строки для «пустых» месяцев, и вам не придется вручную соединять таблицы в тексте запроса.

Итоги и рекомендации

Проанализировав ситуацию, мы пришли к выводу, что залог успеха в группировке дат — это простота запроса и использование штатных механизмов платформы 1С. Постараемся придерживаться следующих правил:

  1. Не соединяйте виртуальные таблицы с таблицами дат без крайней необходимости. Используйте поле Период самой виртуальной таблицы.
  2. Используйте параметры виртуальных таблиц (&НачалоПериода, &КонецПериода) для фильтрации данных на уровне СУБД, а не через секцию ГДЕ.
  3. Всегда проверяйте роли полей в СКД. Если поле называется не Период, система может «запутаться» в его назначении.
  4. Группировку выполняйте средствами СКД в настройках отчета, а не только в тексте запроса через СГРУППИРОВАТЬ ПО. Это даст пользователю больше гибкости при изменении структуры отчета.

Соблюдение этих принципов позволит создавать быстрые, надежные и легко расширяемые отчеты, которые корректно обрабатывают любые временные интервалы.

← На главную