Почему не работает запрос к виртуальной таблице СрезПоследних и как это исправить

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

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

В чем заключается проблема исходного запроса?

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


Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
               |    ОтветственныеЛицаОрганизацийСрезПоследних.ФизическоеЛицо КАК ФизическоеЛицо
               |ИЗ
               |    РегистрСведений.ОтветственныеЛицаОрганизаций.СрезПоследних КАК ОтветственныеЛицаОрганизацийСрезПоследних
               |ГДЕ
               |    ОтветственныеЛицаОрганизацийСрезПоследних.Период = &Период
               |    И ОтветственныеЛицаОрганизацийСрезПоследних.СтруктурнаяЕдиница = &СтруктурнаяЕдиница
               |    И ОтветственныеЛицаОрганизацийСрезПоследних.ОтветственноеЛицо = &ОтветственноеЛицо";

На первый взгляд, синтаксических ошибок здесь нет (после удаления случайной цифры «4»). Однако данный запрос либо вернет пустой результат, либо отработает крайне неэффективно. Причина кроется в фундаментальном различии между фильтрацией данных в секции ГДЕ и использованием параметров самой виртуальной таблицы.

Давайте по шагам проанализируем, почему этот запрос не работает так, как ожидает разработчик.

Причина 1: Логика построения среза последних на уровне СУБД

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

  1. СУБД рассчитывает и выбирает максимальные даты (периоды) для всех уникальных комбинаций измерений (в нашем случае — для всех организаций и всех типов ответственных лиц) на текущую дату и время (на «сейчас»).
  2. Формируется временный набор данных, содержащий только эти самые свежие записи.
  3. И только после этого СУБД начинает накладывать фильтры, описанные в секции ГДЕ. То есть пытается применить условие Период = &Период к уже готовому срезу на текущую дату.

Посмотрим на простом примере:

В регистре сведений есть запись о назначении руководителя от 01.01.2026. Мы проводим документ от 15.01.2026 и передаем эту дату в параметр &Период.

Причина 2: Сравнение времени с точностью до секунд

Даже если бы дата документа чудесным образом в точности совпала с датой установки ответственного лица в регистре, условие Период = &Период в секции ГДЕ практически гарантированно вернет пустое значение. Дело в точности хранения времени:

Оператор равенства в секции ГДЕ требует стопроцентного совпадения времени до секунды. Разница даже в одну секунду приведет к отсеиванию нужной строки. В то же время параметры виртуальной таблицы работают по принципу «меньше или равно» (<= &Период), что позволяет корректно захватывать последнюю актуальную запись на указанный момент времени.

Причина 3: Падение производительности СУБД

Помимо логической ошибки получения пустых данных, использование секции ГДЕ для виртуальных таблиц наносит сильный удар по производительности информационной базы. Рассмотрим, почему это критично для СУБД (особенно под управлением PostgreSQL или MS SQL Server):

Как решить проблему правильно?

Для исправления работы запроса необходимо перенести все отборы из секции ГДЕ непосредственно в параметры виртуальной таблицы СрезПоследних.

Также в конфигурациях семейства Бухгалтерия предприятия 2.0 / 2.5 важно учитывать следующие нюансы:

  1. Составной тип измерения «СтруктурнаяЕдиница»: Это измерение может хранить ссылки как на справочник Организации, так и на ПодразделенияОрганизаций. Убедитесь, что тип передаваемого параметра в точности соответствует типу значения в регистре.
  2. Обработка значений NULL: Если на указанную дату ответственное лицо еще не назначено, запрос вернет пустую строку. Чтобы избежать падения программного кода при чтении детальных записей, рекомендуется использовать функцию ЕСТЬNULL.

Разберем правильный и полностью оптимизированный вариант программного кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ЕСТЬNULL(ОтветственныеЛицаОрганизацийСрезПоследних.ФизическоеЛицо, ЗНАЧЕНИЕ(Справочник.ФизическиеЛица.ПустаяСсылка)) КАК ФизическоеЛицо
    |ИЗ
    |	РегистрСведений.ОтветственныеЛицаОрганизаций.СрезПоследних(
    |		&Период,
    |		СтруктурнаяЕдиница = &СтруктурнаяЕдиница
    |			И ОтветственноеЛицо = &ОтветственноеЛицо
    |	) КАК ОтветственныеЛицаОрганизацийСрезПоследних";

Запрос.УстановитьПараметр("Период", СсылкаНаОбъект.Дата);
Запрос.УстановитьПараметр("СтруктурнаяЕдиница", СсылкаНаОбъект.Организация);
Запрос.УстановитьПараметр("ОтветственноеЛицо", Перечисления.ОтветственныеЛицаОрганизаций.Руководитель);

РезультатЗапроса = Запрос.Выполнить();

Что изменилось в правильном варианте?

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

← На главную