При разработке сложных отчетов или форм списков программисты 1С часто сталкиваются с необходимостью вывести данные из табличной части документа в одну строку через запятую. Одним из наиболее производительных (но в то же время сложных) способов реализации этой задачи является метод «двоичного дерева» или «логарифмического объединения» строк непосредственно в тексте запроса. Однако при использовании этого метода нередко возникает специфическая ошибка: «Неверные параметры Максимум». В этой статье мы подробно разберем, почему возникает эта проблема, как исправить ошибки в коде и какие существуют современные альтернативы.
Метод, который рассматривается в исходной задаче, заключается в последовательном объединении пар строк. Сначала объединяются 1-я и 2-я строки, 3-я и 4-я и так далее. На следующем шаге пакета запросов полученные пары объединяются в четверки, затем в восьмерки. Это позволяет за минимальное количество итераций (log2 от общего количества строк) получить итоговую строку. Для управления этим процессом создается вспомогательная нумерация (НомСтр2), которая на каждом шаге сокращает количество записей вдвое.
Рассмотрим типовой фрагмент такого запроса, где на одном из этапов выполняется свертка:
ВЫБРАТЬ
Шаг.Ссылка КАК Ссылка,
Шаг.НомСтр2 КАК НомСтр1,
МАКСИМУМ(ВЫБОР Шаг.НомСтр2 * 2 - Шаг.НомерСтроки
КОГДА 1 ТОГДА Шаг.УслугаНаименование
ИНАЧЕ ""
КОНЕЦ) +
МАКСИМУМ(ВЫБОР
КОГДА Шаг.Кол = Шаг.НомерСтроки ТОГДА ""
ИНАЧЕ ", "
КОНЕЦ) +
МАКСИМУМ(ВЫБОР Шаг.НомСтр2 * 2 - Шаг.НомерСтроки
КОГДА 1 ТОГДА ""
ИНАЧЕ Шаг.УслугаНаименование
КОНЕЦ) КАК Услуга
ПОМЕСТИТЬ ШагРезультат
ИЗ
Шаг КАК Шаг
СГРУППИРОВАТЬ ПО
Шаг.Ссылка,
Шаг.НомСтр2;
Проанализируем конструкцию ВЫБОР. В языке запросов 1С существует два варианта использования этого оператора. Первый — стандартный, документированный:
ВЫБОР КОГДА Условие ТАКЖЕ Результат ИНАЧЕ Альтернатива КОНЕЦ
Второй — упрощенный аналог switch/case, который пришел из T-SQL:
ВЫБОР Выражение КОГДА Значение ТАКЖЕ Результат КОНЕЦ
Хотя платформа 1С часто «проглатывает» упрощенный синтаксис (поскольку он напрямую транслируется в SQL-запрос), Конструктор запросов может выдавать ошибку «Неверные параметры», если встречает выражение сразу после слова ВЫБОР. Чтобы избежать конфликтов с парсером платформы, рекомендуется всегда использовать полную форму:
ВЫБОР
КОГДА Шаг.НомСтр2 * 2 - Шаг.НомерСтроки = 1
ТОГДА Шаг.УслугаНаименование
ИНАЧЕ ""
КОНЕЦ
Ошибка «Неверные параметры Максимум» чаще всего связана с тем, что платформа не может однозначно определить длину результирующей строки при выполнении сложения внутри агрегатной функции. Когда мы складываем МАКСИМУМ(...) + МАКСИМУМ(...), результат может превысить допустимые пределы или превратиться в строку неограниченной длины, к которой функция МАКСИМУМ неприменима.
Чтобы решить эту проблему, необходимо на каждом шаге явно ограничивать длину строки с помощью функции ВЫРАЗИТЬ. Проанализируем, как это должно выглядеть:
ВЫБРАТЬ
Шаг.Ссылка КАК Ссылка,
ВЫРАЗИТЬ(МАКСИМУМ(...) + МАКСИМУМ(...) КАК СТРОКА(1000)) КАК Услуга
...
Важный нюанс: Если в одном из шагов объединения участвует поле с типом «Строка (неограниченная длина)», функция МАКСИМУМ гарантированно выдаст ошибку. Всегда приводите наименования (услуг, товаров, номенклатуры) к фиксированной длине.
При копировании итераций (Шаг 1, Шаг 2, Шаг 3...) очень легко допустить опечатку. Посмотрим на типичную ошибку из практики:
Шаг3КолВо с полем Колич.Шаг3КолВо.Кол.Несоответствие имен Колич и Кол приведет к тому, что платформа выдаст общую ошибку параметров запроса. Тщательно проверяйте имена полей во всех временных таблицах.
Если задача стоит в контексте вывода данных в Динамический список (на форме списка документов), то использование тяжелых пакетных запросов — это путь к катастрофическому падению производительности. Каждый раз при прокрутке списка сервер будет выполнять десяток вложенных соединений для каждой строки.
Начиная с версии платформы 8.3.15, в Системе компоновки данных (СКД), на которой строятся динамические списки, появилась встроенная функция СоединитьСтроки(). Рассмотрим алгоритм ее применения:
СоединитьСтроки(Массив(Услуги.Услуга.Наименование), ", ")
Это решение работает значительно быстрее, так как платформа оптимизирует получение данных на уровне обращения к СУБД и постобработки в памяти сервера приложений.
Подводя итог, если вы решили продолжать работу с методом «двоичного дерева» в запросе, выполните следующие шаги:
ВЫБОР Выражение КОГДА... на ВЫБОР КОГДА Выражение = Значение....ВЫРАЗИТЬ(... КАК СТРОКА(N)).ЕСТЬNULL(Поле, ""), так как МАКСИМУМ от NULL может вести себя непредсказуемо в сложных выражениях.Кол или Колич) идентичны во всех частях пакета.Помните, что для целей печати или программной обработки гораздо проще и надежнее использовать обычный цикл Для каждого Стр Из ТЧ Цикл в коде модуля, а для интерфейса — возможности СКД.