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