При разработке отчетов на платформе 1С часто возникает задача собрать разрозненные записи регистра в одну сводную строку. Рассмотрим типичную ситуацию: есть регистр накопления Проживание, в котором хранятся данные о заездах физических лиц. По одному человеку может быть несколько записей с разными периодами (например, с 23.06 по 25.06, с 26.06 по 28.06 и с 29.06 по 05.07). Цель — вывести в отчет всего одну строку по этому человеку, где датой заезда будет самое начало проживания (23.06), а датой выезда — самый конец (05.07). Разберем по шагам, как правильно решить эту задачу, какие ошибки часто допускаются и как оформить результат в Системе Компоновки Данных (СКД).
Проанализируем ситуацию, с которой столкнулся разработчик. Изначально для решения задачи использовалась конструкция ВЫБРАТЬ РАЗЛИЧНЫЕ, а также сложный выбор колонок. Посмотрим на логику работы оператора РАЗЛИЧНЫЕ. Он оставляет только уникальные комбинации всех выбранных полей. Так как даты начала и окончания в каждой строке регистра разные, платформа справедливо считает эти строки уникальными и выводит все три записи в результат.
Позже разработчик попытался применить оператор СГРУППИРОВАТЬ ПО, но допустил распространенную ошибку, включив в группировку сами даты:
ВЫБРАТЬ
МИНИМУМ(Проживание.ПериодНачала) КАК ПериодНачала,
МАКСИМУМ(Проживание.ПериодОкончания) КАК ПериодОкончания,
Проживание.Физлицо КАК Физлицо,
Проживание.КолвоДней КАК КолвоДней
ИЗ
РегистрНакопления.Проживание КАК Проживание
ГДЕ
Проживание.Период МЕЖДУ &ДатаЗаезда1 И &ДатаЗаезда2
СГРУППИРОВАТЬ ПО
Проживание.Физлицо,
Проживание.ПериодНачала,
Проживание.ПериодОкончания,
Проживание.КолвоДней
Если мы группируем по полям ПериодНачала и ПериодОкончания, агрегатные функции теряют свой смысл, так как группировка происходит в разрезе каждой уникальной даты. В результате мы снова получаем те же три строки.
Выясним причину и применим правильный подход. Чтобы свернуть данные до одной строки в разрезе физического лица, нам необходимо оставить в секции СГРУППИРОВАТЬ ПО исключительно поле Физлицо (и другие справочные поля, если они нужны, например, ФИО или телефон). Все остальные числовые поля или даты должны обрабатываться агрегатными функциями.
Для дат начала мы используем МИНИМУМ, чтобы найти самый ранний заезд, а для дат окончания — МАКСИМУМ, чтобы зафиксировать последний выезд. Количество дней логично суммировать с помощью СУММА. Рассмотрим исправленный вариант запроса:
ВЫБРАТЬ
МИНИМУМ(Проживание.ПериодНачала) КАК ПериодНачала,
МАКСИМУМ(Проживание.ПериодОкончания) КАК ПериодОкончания,
СУММА(Проживание.КолвоДней) КАК КолвоДней,
Проживание.Физлицо КАК Физлицо
ИЗ
РегистрНакопления.Проживание КАК Проживание
ГДЕ
Проживание.Период МЕЖДУ &ДатаЗаезда1 И &ДатаЗаезда2
СГРУППИРОВАТЬ ПО
Проживание.Физлицо
При таком запросе база данных соберет все записи по конкретному человеку в единый "блок", найдет среди них минимальную дату начала, максимальную дату окончания, сложит дни проживания и выдаст нам ровно одну итоговую строку.
В процессе поиска решения часто возникает предложение использовать виртуальные таблицы, например, РегистрНакопления.Проживание.Обороты. Это логичный шаг для получения итогов, однако в данной задаче кроется важный архитектурный нюанс.
Разберем детально: поле Физлицо в конфигурации автора является реквизитом регистра, а не его измерением. Архитектура платформы 1С устроена таким образом, что виртуальные таблицы (Обороты, Остатки) строятся исключительно в разрезе измерений регистра. Реквизиты служат для хранения дополнительной справочной информации к конкретному движению и в механизм автоматической агрегации не попадают. Следовательно, обратившись к таблице оборотов, мы просто не найдем там поля Физлицо.
Если для аналитики и построения отчетов поле требуется постоянно, методически правильным решением будет реструктуризация метаданных: необходимо перенести Физлицо из реквизитов регистра в его измерения. Если же изменение структуры невозможно, остается использовать физическую таблицу регистра с явной группировкой, как мы сделали в запросе выше.
Рассмотрим еще один критически важный аспект логики. В нашем решении мы берем абсолютный минимум и максимум дат. Но что делать, если в проживании были перерывы? Например, гость жил с 1 по 5 число, затем уехал, и вернулся с 15 по 20 число. Применив МИНИМУМ и МАКСИМУМ, мы получим один период с 1 по 20 число. Система "склеит" даты, и мы посчитаем, что человек проживал непрерывно 20 дней, хотя по факту он отсутствовал 10 дней.
В нашем конкретном случае автор уточнил, что прерывания исключены. Однако, если бы прерывания допускались, задача перешла бы в разряд классической проблемы объединения пересекающихся или смежных интервалов (известной как Gaps and Islands). В 1С она решается двумя основными путями:
ТаблицаЗначений и сортируется по дате начала. Далее с помощью простого цикла перебираются строки: если дата начала следующей строки меньше или равна дате окончания текущей строки, интервалы сливаются путем обновления даты окончания. Если больше — начинается новый независимый интервал.После получения корректных данных часто возникает проблема оформления, в частности — установки понятных заголовков колонок в отчете. Платформа 1С через Систему Компоновки Данных предоставляет несколько гибких инструментов для решения этой задачи. Рассмотрим три способа настройки:
ПериодНачала), выберите пункт "Установить заголовок" и впишите желаемый текст (например, "Дата заезда"). Этот заголовок переопределит синоним поля из исходного запроса.Данные по проживанию с [ПериодНачала] по [ПериодОкончания]. Платформа автоматически подставит значения.ПриКомпоновкеРезультата в модуле объекта отчета. В нем можно программно обратиться к коллекции пользовательских настроек компоновщика и подменить заголовки полей до того, как система сгенерирует финальный табличный документ.Подводя итог, можно сказать, что работа с физическими таблицами регистров накопления требует четкого понимания принципов группировки в SQL-запросах 1С. Важно отличать измерения от реквизитов при использовании виртуальных таблиц, всегда учитывать бизнес-логику (наличие возможных прерываний) и эффективно использовать визуальные инструменты СКД для финализации отчета.