Как правильно настроить отбор по периоду в запросе к регистру сведений 1С

Программист 1С v8.3 (Управляемые формы) Управленческий учет Промышленность, строительство и АПК
← На главную

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

Разница между СрезомПоследних и физической таблицей

Первым делом проанализируем ситуацию: почему запрос к РегистрСведений.ИмяРегистра.СрезПоследних выдает только один документ, даже если их было создано несколько? Виртуальная таблица СрезПоследних предназначена исключительно для получения наиболее актуального (последнего по времени) значения на конкретный момент. Если вы указываете параметр &Период, система ищет последние записи, действующие именно в эту секунду, в разрезе уникальных измерений.

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

Переход к запросу по физической таблице

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

Посмотрим на пример базового запроса с отбором по стандартному полю Период:


ВЫБРАТЬ
    ЧасыРаботыГПУ.Регистратор КАК Регистратор,
    ЧасыРаботыГПУ.Организация КАК Организация,
    ЧасыРаботыГПУ.КоличествоЧасовРаботыГПУ КАК КоличествоЧасовРаботыГПУ
ИЗ
    РегистрСведений.ЧасыРаботыГПУ КАК ЧасыРаботыГПУ
ГДЕ
    ЧасыРаботыГПУ.Период МЕЖДУ &НачДата И &КонДата

В данном примере мы используем оператор МЕЖДУ, который эффективно ограничивает выборку по индексированному полю Период. Это самый быстрый способ получения данных, так как поле Период в периодических регистрах сведений всегда проиндексировано платформой по умолчанию.

Проблема отбора по реквизитам Регистратора

Иногда возникают ситуации, когда стандартного поля Период недостаточно. Например, если в регистр записывается техническая дата (начало месяца), а реальный учетный период хранится внутри самого документа в специальных реквизитах, таких как НачалоУчетногоПериода и ОкончаниеУчетногоПериода.

Выясним причину, почему прямой отбор через точку от регистратора может быть медленным. Рассмотрим следующий код:


ГДЕ
    ЧасыРаботыГПУ.Регистратор.НачалоУчетногоПериода >= &НачДата
    И ЧасыРаботыГПУ.Регистратор.ОкончаниеУчетногоПериода <= &КонДата

Хотя такой запрос технически будет работать и вернет нужные данные, с точки зрения производительности это не самое лучшее решение. Рассмотрим подробнее, что происходит "под капотом":

  1. Неявное соединение: Когда мы пишем Регистратор.Реквизит, платформа 1С выполняет операцию разыменования ссылки. В SQL-запросе это превращается в LEFT JOIN со всеми таблицами документов, которые могут быть регистраторами данного регистра.
  2. Отсутствие индексов: Поля внутри документа (реквизиты) обычно не проиндексированы в контексте таблицы регистра. Это заставляет СУБД сканировать всю таблицу (Full Scan), что приведет к значительным тормозам при росте базы данных.

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

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

Разберем по шагам алгоритм оптимизации:

  1. Создаем временную таблицу, в которую выбираем только ссылки (Ссылка) на нужные документы, фильтруя их по датам НачалоУчетногоПериода и ОкончаниеУчетногоПериода в самой таблице документа.
  2. Соединяем эту временную таблицу с физической таблицей регистра по полю Регистратор.

Такой подход позволит 1С использовать индексы таблиц документов и значительно ускорит выполнение отчета.

Итоговый пример правильного запроса

Посмотрим на итоговый вариант запроса, который объединяет получение данных из регистра и соединение со справочником для получения дополнительных сведений (например, об установках):


ВЫБРАТЬ
    ЧасыРаботыГПУ.Регистратор КАК Регистратор,
    ЧасыРаботыГПУ.Организация КАК Организация,
    ЧасыРаботыГПУ.Площадка КАК Площадка,
    ЧасыРаботыГПУ.ИЗА КАК ИЗА,
    ЧасыРаботыГПУ.КоличествоЧасовРаботыГПУ КАК КоличествоЧасовРаботыГПУ,
    ГазопылевыеУстановки.Ссылка КАК ПГОУ
ИЗ
    РегистрСведений.ЧасыРаботыГПУ КАК ЧасыРаботыГПУ
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ГазопылевыеУстановки КАК ГазопылевыеУстановки
        ПО ЧасыРаботыГПУ.ИЗА = ГазопылевыеУстановки.Владелец
            И (ГазопылевыеУстановки.Основной = ИСТИНА)
ГДЕ
    ЧасыРаботыГПУ.Организация = &Организация
    И ЧасыРаботыГПУ.ИЗА = &ИЗА
    И ЧасыРаботыГПУ.Регистратор.НачалоУчетногоПериода >= &НачДата
    И ЧасыРаботыГПУ.Регистратор.ОкончаниеУчетногоПериода <= &КонДата

Важный момент: Если в регистре записей очень много, обязательно убедитесь, что основные измерения (в данном примере Организация и ИЗА) стоят в начале блока ГДЕ. Это поможет оптимизатору SQL быстрее отсечь ненужные ветки данных.

Полезные советы по работе с периодами

Рассмотрим несколько практических рекомендаций, которые помогут избежать ошибок в будущем:

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

← На главную