При работе с запросами в 1С:Предприятие часто возникает необходимость не просто сгруппировать данные по определенному документу или справочнику, но и выстроить подчиненные записи в хронологическом порядке, а затем скомпоновать текстовые описания из нескольких строк в одну. Рассмотрим, с какими ограничениями платформы можно столкнуться при решении этой задачи и какие существуют проверенные способы их преодоления.
Проанализируем первую часть задачи: как зафиксировать порядок записей при помещении во временную таблицу. По правилам языка запросов 1С, конструкция УПОРЯДОЧИТЬ ПО не может использоваться при создании временной таблицы через оператор ПОМЕСТИТЬ, если не указано ограничение количества выбираемых записей.
Для того чтобы отсортировать строки непосредственно при заполнении временной таблицы, применяют комбинацию ключевых слов ПЕРВЫЕ и УПОРЯДОЧИТЬ ПО:
ВЫБРАТЬ ПЕРВЫЕ 100500
ТЗ_Данные2.Дата КАК Дата,
ТЗ_Данные.Описание КАК Описание,
ТЗ_Данные.СчетФактура КАК СчетФактура
ПОМЕСТИТЬ ТЗ_Результат
ИЗ
ТЗ_Данные КАК ТЗ_Данные
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТЗ_Данные2 КАК ТЗ_Данные2
ПО ТЗ_Данные.СчетФактура = ТЗ_Данные2.СчетФактура
УПОРЯДОЧИТЬ ПО
Дата ВОЗР
;
Важное замечание: согласно стандартам реляционных СУБД (MS SQL Server, PostgreSQL), порядок хранения данных во временных таблицах физически не гарантируется. Даже если таблица создавалась с сортировкой, последующая выборка из нее без явной секции УПОРЯДОЧИТЬ ПО в финальном запросе может вернуть данные в случайном порядке.
Если временная таблица используется для дальнейших соединений, целесообразнее не сортировать ее при создании, а наложить индекс на поля, участвующие в связях и конечной сортировке, с помощью ключевого слова ИНДЕКСИРОВАТЬ ПО.
Рассмотрим вторую часть задачи: объединение текстовых значений из нескольких строк (например, хронологических описаний) в одно поле по каждому документу СчетФактура.
В языке запросов 1С отсутствует встроенная функция вертикальной агрегации строк (аналог STRING_AGG или GROUP_CONCAT из других СУБД). Оператор сложения + выполняет конкатенацию только по горизонтали — между колонками одной и той же строки. Попытка сгруппировать строки по полю СчетФактура не позволит скомпоновать текстовое поле Описание из разных строк.
Выясним, какие варианты решения этой задачи являются наиболее правильными и производительными.
Если задача выполняется в рамках отчета или обработки, использующей СКД, склейка строк выполняется без лишнего кода BSL за счет встроенных функций языка выражений компоновки данных.
Описание в список ресурсов.СоединитьСтроки(Массив(Описание), " ")
СоединитьСтроки(ВычислитьВыражениеСГруппировкойМассив("Описание", "СчетФактура"), " ")
СКД автоматически выполнит группировку по ключевым полям и объединит все текстовые значения в одну строку с указанным разделителем.
Если разработка выполняется во внешнем модуле или процедуре без применения СКД, сборку итогового поля выполняют в коде 1С при обходе результата запроса.
Разберем по шагам правильный алгоритм:
ВЫБРАТЬ
ТЗ_Результат.СчетФактура КАК СчетФактура,
ТЗ_Результат.Дата КАК Дата,
ТЗ_Результат.Описание КАК Описание
ИЗ
ТЗ_Результат КАК ТЗ_Результат
УПОРЯДОЧИТЬ ПО
СчетФактура,
Дата ВОЗР
СтрСоединить:
Выборка = Запрос.Выполнить().Выбрать();
МассивОписаний = Новый Массив;
Пока Выборка.Следующий() Цикл
МассивОписаний.Добавить(Строка(Выборка.Дата) + " " + Выборка.Описание);
КонецЦикла;
ИтоговоеПримечание = СтрСоединить(МассивОписаний, "; ");
Совет по производительности: избегайте склеивания больших строк в цикле через обычное сложение Строка1 + Строка2. Накопление элементов в объекте Массив с последующим вызовом СтрСоединить работает значительно быстрее и не перегружает оперативную память сервера.