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