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

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

При работе с периодическими регистрами сведений в 1С часто возникает задача определить текущее или историческое состояние объекта. Типичный пример — получение списка основных средств (ОС), которые числятся на учете на определенную дату и еще не были списаны.

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

Особенности работы виртуальной таблицы «СрезПоследних»

Разберем важный нюанс работы платформы 1С при передаче условий в виртуальную таблицу СрезПоследних:

  1. Отборы по измерениям: Условия по измерениям (например, ОсновноеСредство = &ОсновноеСредство) необходимо передавать в параметры виртуальной таблицы. Это позволяет СУБД отфильтровать записи на самом раннем этапе и сэкономить ресурсы системы.
  2. Отборы по реквизитам и ресурсам (Логическая ошибка): Если передать условие по ресурсу или реквизиту (например, ВидСобытияОС <> &Списание) непосредственно в параметры виртуальной таблицы, платформа сначала исключит все записи со списанием, а затем найдет последнюю оставшуюся запись. В итоге для списанного ОС запрос вернет предыдущую запись (например, «Принятие к учету»), а не пустой результат.

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

Способ 1. Запрос с подзапросом и проверкой условий

Рассмотрим вариант, когда необходимо проверить статус конкретного основного средства на заданную дату. Мы выбираем запись из среза последних и исключаем объект, если его последним событием было списание.

Проанализируем пример запроса:


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

Обратите внимание: условие по измерению ОсновноеСредство вынесено в параметры виртуальной таблицы СрезПоследних(&Дата, ОсновноеСредство = &ОсновноеСредство), что существенно снижает нагрузку на СУБД.

Способ 2. Оптимальное решение через временные таблицы и ЛЕВОЕ СОЕДИНЕНИЕ

Использование конструкции НЕ В (Подзапрос) может приводить к снижению производительности при выборке большого числа объектов. В реальных конфигурациях для оптимизации запросов рекомендуется использовать временные таблицы и левое соединение с проверкой ЕСТЬ NULL.

Разберем по шагам создание такого запроса:

  1. Получаем актуальные состояния всех ОС на указанную дату и сохраняем их во временную таблицу.
  2. Выбираем списанные ОС из полученной временной таблицы во вторую временную таблицу.
  3. Соединяем таблицы и оставляем только те ОС, у которых нет записи о списании.

// Шаг 1: Получаем срез последних на дату
ВЫБРАТЬ
	СобытияСрез.ОсновноеСредство КАК ОсновноеСредство,
	СобытияСрез.Событие КАК Событие
ПОМЕСТИТЬ ТЗ_АктуальныеСостояния
ИЗ
	РегистрСведений.СобытияОСОрганизаций.СрезПоследних(&Дата, ) КАК СобытияСрез
;

////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Отбираем только списанные ОС
ВЫБРАТЬ
	ТЗ_АктуальныеСостояния.ОсновноеСредство КАК ОсновноеСредство
ПОМЕСТИТЬ ТЗ_СписанныеОС
ИЗ
	ТЗ_АктуальныеСостояния КАК ТЗ_АктуальныеСостояния
ГДЕ
	ТЗ_АктуальныеСостояния.Событие.ВидСобытияОС = &Списание
;

////////////////////////////////////////////////////////////////////////////////
// Шаг 3: Выбираем только действующих (не списанных) ОС
ВЫБРАТЬ
	ТЗ_АктуальныеСостояния.ОсновноеСредство КАК ОсновноеСредство,
	ТЗ_АктуальныеСостояния.Событие КАК Событие
ИЗ
	ТЗ_АктуальныеСостояния КАК ТЗ_АктуальныеСостояния
	ЛЕВОЕ СОЕДИНЕНИЕ ТЗ_СписанныеОС КАК ТЗ_СписанныеОС
		ПО ТЗ_АктуальныеСостояния.ОсновноеСредство = ТЗ_СписанныеОС.ОсновноеСредство
ГДЕ
	ТЗ_СписанныеОС.ОсновноеСредство ЕСТЬ NULL

Способ 3. Получение состояния через программный код 1С

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

Посмотрим на пример реализации на языке 1С:


Отбор = Новый Структура;
Отбор.Вставить("ОсновноеСредство", ВыбранноеОС);

ТаблицаСреза = РегистрыСведений.СобытияОСОрганизаций.СрезПоследних(ДатаПроверки, Отбор);

Если ТаблицаСреза.Количество() > 0 Тогда
	ЗаписьСреза = ТаблицаСреза[0];
	Если ЗаписьСреза.Событие.ВидСобытияОС <> Перечисления.ВидыСобытийОС.Списание Тогда
		// Основное средство числится на учете
		Сообщить("Основное средство находится на учете.");
	Иначе
		// Основное средство списано
		Сообщить("Основное средство списано.");
	КонецЕсли;
КонецЕсли;

Данный подход удобен своей лаконичностью при точечной проверке конкретных элементов в коде встроенного языка.

← На главную