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