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

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

Часто при работе с регистрами сведений в 1С возникает задача получить самую последнюю запись на определенную дату. Первое, что приходит в голову — использовать виртуальную таблицу СрезПоследних. Однако результат может оказаться неожиданным: вместо одной строки запрос возвращает несколько. В этой статье разберем, почему так происходит (кстати, этот вопрос часто задают на собеседованиях при отборе кандидатов) и как правильно получить только одну, самую последнюю запись.

Проанализируем типичную ситуацию. Есть периодический регистр сведений, подчиненный регистратору. Наша цель — получить ссылку на самый последний документ-регистратор для конкретной организации. Мы открываем удобную консоль запросов и пишем, казалось бы, логичный запрос:


ВЫБРАТЬ
    МойРегистрСрезПоследних.Регистратор КАК Регистратор
ИЗ
    РегистрСведений.МойРегистр.СрезПоследних(&Дата, Организация = &Организация) КАК МойРегистрСрезПоследних

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

Причина проблемы: как на самом деле работает СрезПоследних

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

Рассмотрим наш пример из форума. Регистр сведений Ктэ_ЧленыКомиссииОС1 хранит состав комиссии и имеет следующие измерения:

Когда мы делаем запрос к СрезПоследних с отбором по организации, платформа выполняет следующие действия:

  1. Находит все записи регистра, удовлетворяющие условию Организация = &Организация и с периодом, меньшим или равным указанной дате.
  2. Группирует эти записи по уникальным наборам всех измерений. В нашем случае уникальный набор — это связка "Организация + Должность + ФИО + Председатель".
  3. Для каждой такой уникальной группы находит одну самую последнюю по времени запись.
  4. Возвращает все найденные последние записи в итоговой выборке.

Таким образом, если в комиссии для одной организации на последнюю дату было 7 человек (7 уникальных комбинаций ФИО и должности), запрос вернет 7 строк — по одной для каждого члена комиссии. Именно поэтому мы получаем несколько записей вместо одной.

Решение: Как правильно получить одного последнего регистратора

Чтобы решить нашу исходную задачу — получить один, самый свежий по дате регистратор, независимо от состава измерений — нужно отказаться от использования СрезПоследних и обратиться напрямую к физической таблице регистра. Этот подход более гибкий и позволяет точно управлять сортировкой и количеством записей. Рекомендуем даже добавить этот паттерн в свои шаблоны для разработки конфигураций.

Рассмотрим правильный вариант запроса.


ВЫБРАТЬ ПЕРВЫЕ 1
    МойРегистр.Регистратор КАК Регистратор
ИЗ
    РегистрСведений.МойРегистр КАК МойРегистр
ГДЕ
    МойРегистр.Период <= &Дата
    И МойРегистр.Организация = &Организация
УПОРЯДОЧИТЬ ПО
    МойРегистр.Период УБЫВ

Разберем по шагам, что делает этот запрос:

  1. ИЗ РегистрСведений.МойРегистр КАК МойРегистр: Мы обращаемся напрямую к основной таблице регистра, а не к виртуальной.
  2. ГДЕ МойРегистр.Период <= &Дата И МойРегистр.Организация = &Организация: Устанавливаем необходимые отборы по дате и организации.
  3. УПОРЯДОЧИТЬ ПО МойРегистр.Период УБЫВ: Это самый важный шаг. Мы сортируем все найденные записи по полю Период в порядке убывания. Таким образом, самая последняя по времени запись окажется на первом месте.
  4. ВЫБРАТЬ ПЕРВЫЕ 1: После сортировки мы говорим системе взять только первую запись из отсортированного списка. Это и будет самая последняя запись, которую мы искали.

Этот метод является универсальным и самым производительным для получения одной последней записи по заданным условиям.

Бонус: Рекомендации по правильному проектированию регистра

В ходе обсуждения на форуме был поднят важный вопрос о структуре самого регистра сведений. Хранить ФИО и должность членов комиссии в измерениях — не лучшее решение. Такая структура избыточна и усложняет получение данных.

Почему текущая структура не оптимальна?

Когда состав комиссии утверждается документом (регистратором), вся информация (ФИО, должности) уже есть в его табличной части. Дублировать эти данные в измерениях регистра — значит плодить лишнюю информацию. Это усложняет запросы и может негативно сказаться на производительности, о чем подробно рассказывается в материалах про партицированную дисциплину программиста.

Как было бы лучше?

Более грамотная архитектура могла бы выглядеть так:

  1. Создать справочник "Комиссии". В этом справочнике можно хранить всю информацию о комиссии: ее название, председателя и табличную часть "Состав комиссии" с реквизитами "Сотрудник", "Должность" и т.д. Такой справочник будет содержать полный состав конкретной комиссии.

  2. Использовать регистр сведений для фиксации действующих комиссий. Создать периодический регистр сведений, например, "ДействующиеКомиссииОрганизаций", со следующей структурой:

    • Измерения: Организация, НаправлениеДеятельности (если комиссий может быть несколько для разных целей).
    • Ресурсы: Комиссия (здесь будет храниться ссылка на элемент справочника "Комиссии").

При такой структуре документ-регистратор будет делать одну запись в регистр сведений, указывая, какая именно комиссия (ссылка на справочник) действует для данной организации с определенной даты. Запросы станут проще и логичнее: сначала из регистра получаем активную комиссию, а затем из справочника — ее полный состав.

В заключение: запомним два главных правила. Во-первых, виртуальная таблица СрезПоследних возвращает последние записи для каждого уникального набора измерений. Во-вторых, для получения одной самой последней записи по времени используйте прямой запрос к физической таблице с конструкцией ВЫБРАТЬ ПЕРВЫЕ 1 и УПОРЯДОЧИТЬ ПО ... УБЫВ. И, конечно, всегда уделяйте внимание правильному проектированию структуры данных — это залог стабильной и быстрой работы системы.

← На главную