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