Задача получения актуальных цен из документов реализации является одной из самых частых при разработке отчетов или механизмов заполнения цен в 1С. Начинающие разработчики часто допускают ошибку, пытаясь использовать конструкцию ВЫБРАТЬ ПЕРВЫЕ 1, что приводит к получению только одной строки для всего результата запроса вместо последних цен по каждой позиции номенклатуры. В этой статье мы разберем правильные архитектурные подходы к решению этой задачи.
Разберем ситуацию, представленную в исходном вопросе. Когда мы пишем запрос к табличной части Документ.РеализацияТоваровУслуг.Товары и указываем ВЫБРАТЬ ПЕРВЫЕ 1 с сортировкой по дате, система находит самый последний документ и берет из него первую попавшуюся строку. Если нам нужно получить список из 100 товаров с их последними ценами, такой подход не сработает.
Для корректного решения нам необходимо сначала определить, какой документ был последним для каждой номенклатурной позиции, а затем уже «вытащить» цену именно из этой строки. Проанализируем, как это сделать максимально эффективно.
Этот метод считается универсальным, так как он работает в любой конфигурации 1С, где есть документы реализации. Суть заключается в двухэтапном получении данных. Сначала мы находим максимальную дату (или момент времени) для каждой номенклатуры, а затем соединяем этот результат с исходной таблицей товаров.
Рассмотрим пример построения такого запроса по шагам:
Номенклатура и Дата.
ВЫБРАТЬ
РеализацияТовары.Номенклатура КАК Номенклатура,
МАКСИМУМ(РеализацияТовары.Ссылка.Дата) КАК МаксДата
ПОМЕСТИТЬ ВТ_ПоследниеДаты
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
ГДЕ
РеализацияТовары.Ссылка.Проведен = ИСТИНА
И РеализацияТовары.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
РеализацияТовары.Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_ПоследниеДаты.Номенклатура,
РеализацияТовары.Цена,
РеализацияТовары.Ссылка КАК ДокументРеализации
ИЗ
ВТ_ПоследниеДаты КАК ВТ_ПоследниеДаты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
ПО ВТ_ПоследниеДаты.Номенклатура = РеализацияТовары.Номенклатура
И ВТ_ПоследниеДаты.МаксДата = РеализацияТовары.Ссылка.Дата
ГДЕ
РеализацияТовары.Ссылка.Проведен = ИСТИНА
Важный нюанс: Если в одну и ту же секунду проведено несколько документов реализации по одной и той же номенклатуре, запрос может вернуть несколько строк. Чтобы этого избежать, вместо Дата лучше использовать МоментВремени.
В системе 1С МоментВремени — это комбинация даты и уникальной ссылки на документ. Это гарантирует уникальность точки на временной шкале. Проанализируем, как изменить запрос для использования момента времени.
В запросах 1С мы не можем напрямую использовать функцию МАКСИМУМ к объекту типа «Момент времени», поэтому разработчики часто используют связку МАКСИМУМ(Дата) и МАКСИМУМ(Ссылка) внутри этой даты. Однако в современных версиях платформы 8.3 для решения этой задачи в компоновке данных (СКД) предусмотрены специальные механизмы ролей полей периода.
Если в вашей конфигурации при проведении реализации данные записываются в регистр сведений (например, «Цены номенклатуры» или специально созданный регистр «Цены реализации»), это значительно упрощает задачу. Проанализируем преимущества этого метода:
СрезПоследних работает на уровне СУБД крайне эффективно.Пример запроса к регистру сведений:
ВЫБРАТЬ
ЦеныНоменклатурыСрезПоследних.Номенклатура,
ЦеныНоменклатурыСрезПоследних.Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК ЦеныНоменклатурыСрезПоследних
В современных управленческих конфигурациях (Управление торговлей 11, ERP, Комплексная автоматизация) данные о продажах фиксируются в регистре накопления ВыручкаИСебестоимостьПродаж. Выясним, почему выгодно брать данные оттуда:
Во-первых, этот регистр содержит информацию о чистой выручке и количестве. Мы можем рассчитать среднюю цену продажи за период или найти последний документ-регистратор. Во-вторых, в этом регистре уже учтены возвраты и корректировки, что критически важно для получения достоверной цены.
Рассмотрим подробнее нюансы, которые часто забывают при написании запросов, что приводит к ошибкам в данных:
Номенклатура + Характеристика. Обязательно добавляйте группировку по характеристике, иначе вы получите неверную цену для товаров с разными свойствами.Цена на Коэффициент из справочника упаковок.Проведен = ИСТИНА и ПометкаУдаления = ЛОЖЬ. Непроведенные документы не являются фактом совершения сделки и не должны влиять на актуальную цену.Посмотрим на ситуацию со стороны создания отчета. В СКД реализован мощный механизм для получения последних значений. Если вы укажете в настройках набора данных роль для поля периода («Период») и правильно настроите ресурсы, СКД сможет самостоятельно рассчитать последнее значение цены для каждой строки группировки. Это избавит вас от необходимости писать громоздкие вложенные запросы вручную.
Подводя итог, можно сказать, что выбор метода зависит от архитектуры вашей базы данных. Если есть возможность использовать специализированные регистры — используйте их. Если же нужно тянуть данные напрямую из документов, всегда помните о группировке по Моменту времени и необходимости фильтрации проведенных документов.