Как в 1С получить последнюю закупочную цену номенклатуры без учета поставщика

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

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

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

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

Виртуальная таблица СрезПоследних рассчитывает срез в разрезе всех измерений. Это означает, что если в параметрах виртуальной таблицы не задан жесткий отбор по конкретному поставщику, платформа вернет самую свежую запись для каждой уникальной пары «Номенклатура + Поставщик». Если товар закупался у трех разных контрагентов, в результате запроса появятся 3 строки с разными ценами, даже если требуется получить только одну — самую последнюю по времени цену закупки.

Пошаговое решение задачи с помощью пакетного запроса

Разберем по шагам, как обойти ограничение виртуальной таблицы и выгрузить строго последнюю цену закупки независимо от того, какой поставщик ее предоставил.

  1. Выборка максимального периода по номенклатуре: Из физической таблицы регистра сведений выбираем номенклатуру и находим максимальную дату (период) установки цены с помощью агрегатной функции МАКСИМУМ. Результат помещаем во временную таблицу.
  2. Соединение исходных данных с максимальным периодом: Соединяем временную таблицу среза максимальных дат с физической таблицей регистра по полям Номенклатура и Период, чтобы достать значение цены на эту дату.

Рассмотрим пример правильного текста запроса:


ВЫБРАТЬ
	ЦеныНоменклатуры.Номенклатура КАК Номенклатура,
	МАКСИМУМ(ЦеныНоменклатуры.Период) КАК Период
ПОМЕСТИТЬ ТЗ_МаксимальныеДаты
ИЗ
	РегистрСведений.ЦеныНоменклатурыПоставщиков КАК ЦеныНоменклатуры
СГРУППИРОВАТЬ ПО
	ЦеныНоменклатуры.Номенклатура
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	МаксДаты.Номенклатура КАК Номенклатура,
	МАКСИМУМ(ЦеныНоменклатуры.Цена) КАК Цена
ПОМЕСТИТЬ ЦеныЗакупки
ИЗ
	ТЗ_МаксимальныеДаты КАК МаксДаты
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатурыПоставщиков КАК ЦеныНоменклатуры
		ПО МаксДаты.Номенклатура = ЦеныНоменклатуры.Номенклатура
			И МаксДаты.Период = ЦеныНоменклатуры.Период
СГРУППИРОВАТЬ ПО
	МаксДаты.Номенклатура

Важные технические нюансы и обработка коллизий

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

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

2. Обязательное условие соединения по периоду. При левом или внутреннем соединении таблицы цен с максимальными датами критически важно указать два поля связи:


ПО МаксДаты.Номенклатура = ЦеныНоменклатуры.Номенклатура
	И МаксДаты.Период = ЦеныНоменклатуры.Период

Если опустить условие по полю Период, запрос просто объединит каждую номенклатуру со всеми ее историческими ценами, и проблема дублирования строк останется нерешенной.

3. Защита от дублей при совпадении периодов (коллизия дат). В практической работе возможна ситуация, когда в одну и ту же секунду были зарегистрированы цены от двух разных поставщиков. В таком случае условие по периоду вернет две записи на один и тот же момент времени. Чтобы избежать двоения позиций в итоговой таблице, во втором пакете запроса применяется группировка по полю Номенклатура и выбирается МАКСИМУМ(Цена) или МИНИМУМ(Цена) в зависимости от задач бизнес-логики.

← На главную