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