Как получить состояние сотрудника или актуальные данные регистра сведений на каждую дату месяца?

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

Одной из наиболее распространенных задач при разработке отчетов в 1С является получение актуальных данных из периодического регистра сведений на каждый день заданного периода. Часто разработчики сталкиваются с вопросом, как правильно соединить календарный период с данными регистра, чтобы не потерять производительность и избежать непредсказуемых результатов.

Разбор проблемы: почему стандартные методы могут работать медленно

Чаще всего начинающие разработчики пытаются использовать СрезПоследних внутри цикла или соединяют таблицу дат с результатом сложного вложенного запроса. Как мы выяснили, использование конструкции ВЫБРАТЬ ПЕРВЫЕ 1 во вложенном запросе — это не самый надежный путь, так как он не гарантирует получение корректных данных и может приводить к «плавающим» результатам, если в регистре для одной даты существует несколько записей. Кроме того, чрезмерное использование вложенных запросов усложняет читаемость кода и может негативно сказываться на планах выполнения запросов в СУБД.

Оптимальное решение: использование пакета запросов и временных таблиц

Рассмотрим профессиональный подход, который заключается в использовании временных таблиц. Этот метод позволяет значительно повысить производительность, так как СУБД может создать индексы по полям соединения. Мы разберем этот процесс по шагам.

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

Пошаговое руководство по созданию эффективного запроса

  1. Создание таблицы актуальных периодов: Сначала мы вычисляем максимальный период записи, который меньше или равен дате календаря. Это позволяет нам «привязать» состояние к каждому дню.
  2. Соединение с основной таблицей: Получив точный период, мы делаем финальное соединение с физической таблицей регистра, чтобы забрать сами данные (состояние).

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


ВЫБРАТЬ
    ТаблицаДат.ДатаКалендаря,
    МАКСИМУМ(Регистр.Период) КАК Период
ПОМЕСТИТЬ ВременнаяТаблицаПериодов
ИЗ
    ТаблицаДат КАК ТаблицаДат
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СостояниеСотрудниковОрганизаций КАК Регистр
    ПО ТаблицаДат.ДатаКалендаря >= Регистр.Период
СГРУППИРОВАТЬ ПО
    ТаблицаДат.ДатаКалендаря;

ВЫБРАТЬ
    ВременнаяТаблицаПериодов.ДатаКалендаря,
    Регистр.Сотрудник,
    Регистр.Состояние
ИЗ
    ВременнаяТаблицаПериодов КАК ВременнаяТаблицаПериодов
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СостояниеСотрудниковОрганизаций КАК Регистр
    ПО ВременнаяТаблицаПериодов.Период = Регистр.Период

Почему этот метод эффективен?

Давайте проанализируем, почему именно этот вариант считается «золотым стандартом» в разработке на 1С:

Практические рекомендации

При работе с такими запросами помните следующие важные правила:

Во-первых, избегайте вложенных запросов, когда это возможно. Как было отмечено, их использование в сложных отчетах не только затрудняет чтение кода, но и может приводить к потере быстродействия при выполнении запроса к СУБД.

Во-вторых, всегда обращайте внимание на индексы. Если вы работаете с очень большими объемами данных, убедитесь, что поле Период в регистре сведений проиндексировано. Это сделает соединение по условию «меньше или равно» практически мгновенным.

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

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

← На главную