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