При работе с регистрами сведений в 1С часто возникает задача получить актуальные (последние) значения, но только те, которые удовлетворяют определенному условию. Например, найти все товары, у которых текущая цена равна 100 рублям. Интуитивно кажется, что условие Цена = 100 можно поместить прямо в параметры виртуальной таблицы СрезПоследних. Однако такой подход приводит к неверным результатам. Разберемся, почему так происходит и как правильно выполнять такую фильтрацию.
Ключ к пониманию проблемы лежит в последовательности действий, которые платформа 1С выполняет при обработке запроса к виртуальной таблице СрезПоследних или СрезПервых. Этот механизм строго регламентирован, и его понимание помогает избежать логических ошибок.
Проанализируем шаги платформы:
Условие). Все записи, которые не удовлетворяют этому условию, отбрасываются.СрезПоследних) или самую первую (для СрезПервых) по дате.Основная проблема заключается в том, что фильтрация по параметру Условие происходит до получения среза, а не после. Если последняя актуальная запись не попадет под условие фильтрации, она будет исключена из рассмотрения, и система будет искать "последнюю" запись среди более старых, которые прошли фильтр. Это полностью искажает саму суть среза как механизма получения актуальных данных на определенный момент времени.
Представим себе периодический регистр сведений ЦеныНоменклатуры со следующей структурой:
Номенклатура (СправочникСсылка.Номенклатура)Цена (Число)В регистре есть две записи для товара "Стол письменный":
Наша задача — получить срез на 20.02.2023 и узнать, есть ли товары с актуальной ценой 5000. Попробуем сделать это "неправильным" способом, установив отбор по ресурсу в параметрах виртуальной таблицы.
// НЕПРАВИЛЬНЫЙ запрос
ВЫБРАТЬ
Цены.Номенклатура,
Цены.Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
&ДатаСреза,
Цена = 5000 // Отбор по ресурсу в параметрах
) КАК Цены
Проследим, что сделает платформа при выполнении этого запроса:
Цена = 5000. Запись от 15.02.2023 (с ценой 5500) будет отброшена.Это неверный результат. На дату среза (20.02.2023) актуальная цена товара — 5500. Запрос же сообщил нам, что последняя цена равна 5000, что является устаревшей информацией. Мы получили не "последнюю запись, у которой цена равна 5000", а "последнюю запись из тех, у которых цена равна 5000".
Чтобы получить корректный результат, необходимо сначала получить полный срез актуальных данных, а уже затем отфильтровать полученный результат. Для этого используется оператор ГДЕ основного запроса.
Посмотрим на правильный вариант запроса:
// ПРАВИЛЬНЫЙ запрос
ВЫБРАТЬ
ЦеныСрезПоследних.Номенклатура,
ЦеныСрезПоследних.Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаСреза, ) КАК ЦеныСрезПоследних
ГДЕ
ЦеныСрезПоследних.Цена = 5000 // Отбор по ресурсу в секции ГДЕ
В этом случае логика выполнения будет следующей:
СрезПоследних формируется без предварительного отбора по ресурсу. Для товара "Стол письменный" она корректно найдет последнюю запись от 15.02.2023 и вернет актуальную цену 5500.ГДЕ ЦеныСрезПоследних.Цена = 5000.Этот результат является правильным: на 20.02.2023 нет товаров с актуальной ценой 5000. Мы сначала получили истинное состояние данных, а потом отфильтровали его.
В ходе обсуждения подобных тем часто возникает вопрос о различиях между ресурсами и реквизитами регистра сведений. Это важное архитектурное различие, напрямую связанное с механизмом срезов.
Ресурсы — это основные, изменяемые во времени данные, которые мы хотим отслеживать. Это "состояние" объекта в разрезе измерений. Именно для получения значений ресурсов и предназначены срезы. Примеры: Цена товара, Курс валюты, Состояние сотрудника (работает, в отпуске).
Реквизиты — это дополнительная, статичная информация, которая характеризует не само состояние, а конкретный факт (запись) его изменения. Реквизиты не являются периодическими и не участвуют в механизме среза напрямую, но их можно получить вместе с ресурсами из той записи, которая попала в срез. Примеры: Пользователь, установивший цену; Документ-основание, которым было изменено состояние; Комментарий к изменению.
Ключевой вывод: Используйте параметр Условие в виртуальных таблицах среза только для отбора по измерениям или реквизитам, если вам нужно ограничить исходный набор данных для анализа. Для фильтрации по значению ресурса всегда используйте конструкцию ГДЕ в основном запросе.