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