Почему нельзя использовать отбор по ресурсу в параметрах виртуальной таблицы среза 1С?

Программист IT и автоматизация бизнеса
← На главную

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

Как на самом деле работает механизм среза

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

Проанализируем шаги платформы:

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

Основная проблема заключается в том, что фильтрация по параметру Условие происходит до получения среза, а не после. Если последняя актуальная запись не попадет под условие фильтрации, она будет исключена из рассмотрения, и система будет искать "последнюю" запись среди более старых, которые прошли фильтр. Это полностью искажает саму суть среза как механизма получения актуальных данных на определенный момент времени.

Рассмотрим на практическом примере

Представим себе периодический регистр сведений ЦеныНоменклатуры со следующей структурой:

В регистре есть две записи для товара "Стол письменный":

Наша задача — получить срез на 20.02.2023 и узнать, есть ли товары с актуальной ценой 5000. Попробуем сделать это "неправильным" способом, установив отбор по ресурсу в параметрах виртуальной таблицы.


// НЕПРАВИЛЬНЫЙ запрос
ВЫБРАТЬ
    Цены.Номенклатура,
    Цены.Цена
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
        &ДатаСреза,
        Цена = 5000 // Отбор по ресурсу в параметрах
    ) КАК Цены

Проследим, что сделает платформа при выполнении этого запроса:

  1. Система возьмет обе записи из регистра.
  2. Применит условие Цена = 5000. Запись от 15.02.2023 (с ценой 5500) будет отброшена.
  3. Теперь для механизма среза осталась только одна запись для товара "Стол письменный" — от 10.01.2023 с ценой 5000.
  4. В результате запрос вернет строку: "Стол письменный", 5000.

Это неверный результат. На дату среза (20.02.2023) актуальная цена товара — 5500. Запрос же сообщил нам, что последняя цена равна 5000, что является устаревшей информацией. Мы получили не "последнюю запись, у которой цена равна 5000", а "последнюю запись из тех, у которых цена равна 5000".

Правильный способ фильтрации по значению ресурса

Чтобы получить корректный результат, необходимо сначала получить полный срез актуальных данных, а уже затем отфильтровать полученный результат. Для этого используется оператор ГДЕ основного запроса.

Посмотрим на правильный вариант запроса:


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

В этом случае логика выполнения будет следующей:

  1. Виртуальная таблица СрезПоследних формируется без предварительного отбора по ресурсу. Для товара "Стол письменный" она корректно найдет последнюю запись от 15.02.2023 и вернет актуальную цену 5500.
  2. Далее к этому результату (полному срезу) применяется условие ГДЕ ЦеныСрезПоследних.Цена = 5000.
  3. Поскольку актуальная цена товара (5500) не равна 5000, эта строка не попадет в итоговую выборку.

Этот результат является правильным: на 20.02.2023 нет товаров с актуальной ценой 5000. Мы сначала получили истинное состояние данных, а потом отфильтровали его.

Вспомогательный вопрос: Ресурсы и Реквизиты — в чем разница?

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

Ресурсы — это основные, изменяемые во времени данные, которые мы хотим отслеживать. Это "состояние" объекта в разрезе измерений. Именно для получения значений ресурсов и предназначены срезы. Примеры: Цена товара, Курс валюты, Состояние сотрудника (работает, в отпуске).

Реквизиты — это дополнительная, статичная информация, которая характеризует не само состояние, а конкретный факт (запись) его изменения. Реквизиты не являются периодическими и не участвуют в механизме среза напрямую, но их можно получить вместе с ресурсами из той записи, которая попала в срез. Примеры: Пользователь, установивший цену; Документ-основание, которым было изменено состояние; Комментарий к изменению.

Ключевой вывод: Используйте параметр Условие в виртуальных таблицах среза только для отбора по измерениям или реквизитам, если вам нужно ограничить исходный набор данных для анализа. Для фильтрации по значению ресурса всегда используйте конструкцию ГДЕ в основном запросе.

← На главную