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