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