При разработке в 1С часто возникает задача проверить наличие данных в регистрах сведений. Одной из типичных проблем является получение актуальных цен номенклатуры при загрузке документа. Многие начинающие разработчики сталкиваются с трудностями, когда регистр ЦеныНоменклатуры подчинен регистратору, ошибочно полагая, что это накладывает ограничения на выборку данных. Давайте разберем, как решить эту задачу профессионально, не прибегая к медленным запросам в цикле.
Основное заблуждение заключается в мнении, что если регистр ЦеныНоменклатуры подчинен регистратору, то к нему невозможно обратиться без указания конкретного регистратора. На самом деле, это не так. Механизм подчинения регистратору определяет способ записи данных (через конкретный документ), но не ограничивает возможности чтения с помощью виртуальных таблиц.
Главная ошибка, которую стоит избегать — это выполнение запроса внутри цикла обхода ТаблицыЗначений с товарами. Такой подход (проблема N+1) катастрофически сказывается на производительности: для каждой позиции система обращается к серверу баз данных, что вызывает избыточные блокировки и сетевые задержки. Мы же хотим работать быстро и «спортивно».
Для решения задачи оптимальным способом является использование временных таблиц. Суть метода заключается в том, чтобы передать весь список товаров одним махом в запрос и выполнить соединение с виртуальной таблицей СрезПоследних. Это позволит получить все необходимые цены за одну операцию.
Рассмотрим пошаговый алгоритм действий:
ПОМЕСТИТЬ.РегистрСведений.ЦеныНоменклатуры.СрезПоследних по полям Номенклатура и ВидЦены.Давайте посмотрим, как выглядит структура такого запроса. Предположим, у нас есть ТаблицаТоваров, которую мы передаем как параметр СписокТоваров:
ВЫБРАТЬ
ТЗ.Номенклатура,
ТЗ.ВидЦены
ПОМЕСТИТЬ ВремТаблицаТоваров
ИЗ
&СписокТоваров КАК ТЗ
;
ВЫБРАТЬ
ВремТаблицаТоваров.Номенклатура,
ВремТаблицаТоваров.ВидЦены,
ЕСТЬNULL(СрезЦен.Цена, 0) КАК ТекущаяЦена
ИЗ
ВремТаблицаТоваров КАК ВремТаблицаТоваров
ЛЕВОЕ СОЕДИНЕНИЕ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ТекДата, ) КАК СрезЦен
ПО
ВремТаблицаТоваров.Номенклатура = СрезЦен.Номенклатура
И ВремТаблицаТоваров.ВидЦены = СрезЦен.ВидЦены
Разберем подробнее, что происходит при выполнении данного кода:
Номенклатура и ВидЦены.ЛЕВОГО СОЕДИНЕНИЯ, если запись в регистре отсутствует, результатом будет NULL. Мы обрабатываем это через функцию ЕСТЬNULL, что позволяет сразу определить, была ли цена установлена ранее.Теперь вы знаете, как правильно работать с периодическими регистрами сведений. Забываем про циклы с запросами внутри — используем мощь временных таблиц и возможностей языка запросов 1С!