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