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