При разработке алгоритмов заполнении табличных частей документов или формировании отчетов часто возникает задача получить цены номенклатуры, актуальные строго на момент (дату и время) проведения или создания документа. Разберем, как корректно написать запрос в 1С для решения этой задачи и какие нюансы следует учитывать.
Для получения актуальных сведений из периодического регистра сведений на заданную дату в платформе 1С предусмотрена виртуальная таблица СрезПоследних. Если необходимо получить цены для строк табличной части конкретного документа, обращение к виртуальной таблице РегистрСведений.ЦеныНоменклатуры.СрезПоследних с передачей даты документа в параметр периода является наиболее правильным и эффективным подходом.
Рассмотрим стандартный пример запроса для заполнения цен в документе:
ВЫБРАТЬ
ТЧТовары.Номенклатура КАК Номенклатура,
ТЧТовары.Характеристика КАК Характеристика,
ЕСТЬNULL(ЦеныСрез.Цена, 0) КАК Цена
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК ТЧТовары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
&ДатаДокумента,
ВидЦены = &ВидЦены
) КАК ЦеныСрез
ПО ТЧТовары.Номенклатура = ЦеныСрез.Номенклатура
И ТЧТовары.Характеристика = ЦеныСрез.Характеристика
ГДЕ
ТЧТовары.Ссылка = &СсылкаДокумента
Выясним, почему попытка обращаться напрямую к реальной (физической) таблице регистра сведений с простым условием по периоду не даст нужного результата. Проанализируем типичную ситуацию из практики:
Если написать запрос к физической таблице регистра с условием равенства дат (Период = &ДатаДокумента), запрос не вернет ни одной записи, так как 10 августа цены не менялись. Если же написать условие Период <= &ДатаДокумента, запрос вернет абсолютно все исторические записи по данной номенклатуре за все время до 10 августа, что приведет к дублированию строк в итоговом результате. Чтобы найти именно последнее значение, придется вручную группировать данные по максимальному периоду. Виртуальная таблица СрезПоследних делает эту работу автоматически на уровне СУБД.
Разберем основные правила оптимизации при работе с регистром цен:
ГДЕ или условия соединения ПО. Если отбор не указан в параметрах таблицы, СУБД сформирует срез последних по всем существующим позициям в базе, что приведет к сильному падению скорости.NULL. Обязательно используйте функцию ЕСТЬNULL(ТаблицаЦен.Цена, 0) для защиты от ошибок в последующих расчетах.Граница с указанием вида границы (ВидГраницы.Включая или ВидГраницы.Исключая).При написании запросов важно брать во внимание версию конфигурации:
В конфигурации УТ 10.3 используется измерение ТипЦен, а периодичность регистра, как правило, составляет один день. Запрос к регистру сведений ЦеныНоменклатуры.СрезПоследних работает напрямую и возвращает зафиксированные значения.
В конфигурации УТ 11 ценообразование устроено сложнее. Измерение называется ВидЦены. Кроме того, виды цен могут быть динамическими (например, рассчитываемыми по формуле от базовой цены). Физических записей в регистре для таких цен не создается, поэтому прямой запрос к регистру сведений вернет пустое значение. Для УТ 11 при работе с произвольными видами цен рекомендуется использовать типовые программные модули ценообразования (например, ОбработкаТабличнойЧастиСервер.ЗаполнитьЦены... или программные функции получения цен).