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