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

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

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

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

Распространенные ошибки при составлении запроса

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

  1. Использование агрегатной функции МАКСИМУМ(Ссылка). Сравнение ссылочных полей происходит по уникальному идентификатору (GUID). GUID гарантирует хронологический порядок только в рамках одной сессии платформы. При переносе данных или групповой загрузке GUID более позднего документа может оказаться меньше GUID ранее созданного документа.
  2. Задвоение строк при одинаковых датах. Если несколько документов проверены в одну и ту же секунду, объединение таблиц только по номенклатуре и дате приведет к умножению строк и получению нескольких «последних» цен.
  3. Неявные соединения и падение производительности. Обращение к реквизитам шапки через точки из табличной части (например, ПриобретениеТоваровУслугТовары.Ссылка.Дата или Ссылка.Проведен) создаёт неявное соединение (LEFT JOIN) к таблице документов для каждой строки, что сильно замедляет запрос на больших объемах данных.
  4. Учет непроведенных документов. Без фильтрации по статусу проведения в результат попадут цены из непроведенных документов или черновиков.

Правильный алгоритм решения задачи

Чтобы корректно скомпоновать «срез последних» ручными средствами в запросе, разберем по шагам логику работы с временными таблицами:

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

Пример запроса для получения последней цены

Рассмотрим практический пример запроса для документа ПриобретениеТоваровУслуг (Управление торговлей 11 / ERP):


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

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

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

Оптимизация и устранение коллизий

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

  1. Для предотвращения задвоения при совпадении дат документов на втором шаге можно выбирать не просто МАКСИМУМ(Дата), а делать двухуровневое определение победителя: сначала находить максимальную дату, затем максимальную ссылку на документ за эту дату.
  2. Если номенклатура может встречаться в документе несколько раз (например, с разными характеристиками или упаковками), в условие связи временных таблиц следует обязательно добавлять группировку по аналитическим разрезам (Характеристика, Упаковка) или брать максимальный номер строки МАКСИМУМ(НомерСтроки).
  3. Если в вашей системе ведутся регистры сведений по ценам номенклатуры (например, ЦеныНоменклатуры.СрезПоследних) или регистры накопления (например, Закупки.Обороты), предпочтительнее делать выборку из виртуальных таблиц регистров — это работает значительно быстрее, чем прямые запросы к табличным частям документов.
← На главную