Как эффективно получить данные из регистра сведений, подчиненного регистратору, без выполнения запросов в цикле?

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

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

Разбор проблемы и заблуждений

Основное заблуждение заключается в мнении, что если регистр ЦеныНоменклатуры подчинен регистратору, то к нему невозможно обратиться без указания конкретного регистратора. На самом деле, это не так. Механизм подчинения регистратору определяет способ записи данных (через конкретный документ), но не ограничивает возможности чтения с помощью виртуальных таблиц.

Главная ошибка, которую стоит избегать — это выполнение запроса внутри цикла обхода ТаблицыЗначений с товарами. Такой подход (проблема N+1) катастрофически сказывается на производительности: для каждой позиции система обращается к серверу баз данных, что вызывает избыточные блокировки и сетевые задержки. Мы же хотим работать быстро и «спортивно».

Решение: использование временных таблиц и СрезаПоследних

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

Рассмотрим пошаговый алгоритм действий:

  1. Создаем запрос к базе данных.
  2. Передаем таблицу значений с товарами в качестве параметра запроса.
  3. Помещаем эту таблицу во временную таблицу с помощью конструкции ПОМЕСТИТЬ.
  4. Соединяем временную таблицу с виртуальной таблицей РегистрСведений.ЦеныНоменклатуры.СрезПоследних по полям Номенклатура и ВидЦены.

Пример реализации кода

Давайте посмотрим, как выглядит структура такого запроса. Предположим, у нас есть ТаблицаТоваров, которую мы передаем как параметр СписокТоваров:


ВЫБРАТЬ
    ТЗ.Номенклатура,
    ТЗ.ВидЦены
ПОМЕСТИТЬ ВремТаблицаТоваров
ИЗ
    &СписокТоваров КАК ТЗ
;

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

Почему этот метод эффективен?

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

Теперь вы знаете, как правильно работать с периодическими регистрами сведений. Забываем про циклы с запросами внутри — используем мощь временных таблиц и возможностей языка запросов 1С!

← На главную