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