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