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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Рассмотрим, почему возникает эта проблема, и разберем проверенные способы её решения как с помощью языка запросов, так и путем изменения архитектуры базы данных.

Почему СрезПоследних возвращает лишние строки

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

Если структура регистра содержит измерения Контрагент, Продукт и Материал, то платформа считает уникальной каждую комбинацию всех трех полей. Если Первым документом были записаны Материал1 и Материал2, а Вторым — Материал3, то для платформы комбинации (Контрагент1, Продукт1, Материал1) и (Контрагент1, Продукт1, Материал3) являются разными разрезами учета. В результате срез последних вернет все три материала, так как для первых двух записей не было вытесняющих движений с теми же значениями измерений.

Способ 1. Запрос с поиском максимального периода или регистратора

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

  1. Создадим временную таблицу, в которой сгруппируем данные по ключевым измерениям (Контрагент, Продукт) и вычислим максимальный период (или максимальную ссылку на документ-регистратор).
  2. Соединим полученную временную таблицу с физической таблицей регистра сведений по измерениям и найденному максимальному периоду.

Проанализируем пример кода такого запроса:


ВЫБРАТЬ
	РС.Контрагент КАК Контрагент,
	РС.Продукт КАК Продукт,
	МАКСИМУМ(РС.Период) КАК Период
ПОМЕСТИТЬ ВТ_МаксимальныйПериод
ИЗ
	РегистрСведений.СоставПродукции КАК РС
ГДЕ
	РС.Контрагент = &Контрагент
	И РС.Продукт = &Продукт
ГРУППИРОВАТЬ ПО
	РС.Контрагент,
	РС.Продукт;

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

Обратите внимание на производительность: Чтобы такой запрос выполнялся быстро, измерения Контрагент и Продукт должны стоять первыми в списке измерений регистра сведений, а для них должно быть включено свойство Индексировать.

Способ 2. Реструктуризация данных через Справочник (Спецификации)

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

Для решения этой задачи применим следующий шаблон проектирования:

  1. Создадим справочник (например, Спецификации), где в табличной части хранятся строки с полем Материал.
  2. В регистре сведений оставим измерения Контрагент и Продукт, а в качестве ресурса укажем ссылку на справочник Спецификации.

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


ВЫБРАТЬ
	Срез.Контрагент КАК Контрагент,
	Срез.Продукт КАК Продукт,
	ТЧ.Материал КАК Материал
ИЗ
	РегистрСведений.СоставПродукции.СрезПоследних(&Период, Контрагент = &Контрагент И Продукт = &Продукт) КАК Срез
	ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Спецификации.Состав КАК ТЧ
		ПО Срез.Спецификация = ТЧ.Ссылка

Способ 3. Связка среза последних с табличной частью документа

Посмотрим еще на один вариант, когда регистр хранит только головную информацию (шапку), а сами материалы выбираются напрямую из документа-регистратора.

В этом случае измерениями регистра остаются Контрагент и Продукт (без подчиненного измерения Материал). Запрос к актуальному набору данных будет выглядеть следующим образом:


ВЫБРАТЬ
	Срез.Контрагент КАК Контрагент,
	Срез.Продукт КАК Продукт,
	ТЧ.Материал КАК Материал
ИЗ
	РегистрСведений.СоставПродукции.СрезПоследних(&Период, Контрагент = &Контрагент И Продукт = &Продукт) КАК Срез
	ЛЕВОЕ СОЕДИНЕНИЕ Документ.УстановкаСостава.Материалы КАК ТЧ
		ПО Срез.Регистратор = ТЧ.Ссылка

Важное ограничение: Соединение регистра с табличной частью документа подходит для небольших объемов данных. На крупных базах прямое соединение с табличными частями документов может замедлять работу СУБД, поэтому предпочтение следует отдавать выносу состава в справочник (Способ 2) или соединению по временной таблице (Способ 1).

← На главную