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