Как в СКД передать список значений в параметр и избежать ошибки несовместимости типов?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов на системе компоновки данных (СКД) разработчики часто сталкиваются с задачей выбора нескольких значений одного объекта — например, нескольких контрагентов, номенклатурных позиций или складов. Если просто включить флаг Доступен список значений на вкладке «Параметры», платформа может выдать ошибку о сравнении несовместимых типов или строк неограниченной длины. Разберем причины возникновения этой ошибки и рассмотрим корректные способы ее решения.

Почему возникает ошибка при включении списка значений

Проанализируем исходную ситуацию. В тексте запроса жестко прописано условие равенства:


ГДЕ
    Контрагенты.Ссылка = &Контрагент

Оператор равенства = в языке запросов 1С рассчитан исключительно на работу с одиночным значением (скалярным типом, например конкретной ссылкой СправочникСсылка.Контрагенты). Когда в настройках параметра СКД мы устанавливаем флаг Доступен список значений, тип передаваемого значения трансформируется в коллекцию (объект СписокЗначений или массив). При попытке сравнить ссылку со списком СУБД сообщает о несовместимости типов данных.

Для исправления ситуации можно использовать несколько подходов в зависимости от требований к отчету и удобства пользователей.

Способ 1. Изменение условия в тексте запроса

Если необходимо оставить именно параметр СКД, изменим оператор сравнения в секции ГДЕ. Для работы с коллекциями значений в языке запросов 1С применяются операторы В и В ИЕРАРХИИ.

  1. Использование оператора В: проверяет вхождение ссылки в указанный список элементов:
    
    ГДЕ
        Контрагенты.Ссылка В (&Контрагент)
    
  2. Использование оператора В ИЕРАРХИИ: подходит, если в списке могут присутствовать группы справочника, и требуется получить данные как по самим группам, так и по всем их дочерним элементам:
    
    ГДЕ
        Контрагенты.Ссылка В ИЕРАРХИИ (&Контрагент)
    

Важное замечание: если условие прописано жестко в основном тексте запроса без расширения СКД, параметр &Контрагент станет обязательным к заполнению. Если пользователь оставит список пустым, запрос не вернет строк либо завершится с ошибкой.

Чтобы условие накладывалось только тогда, когда параметр действительно заполнен пользователем, воспользуемся синтаксисом расширения языка запросов компоновки данных (фигурные скобки):


{ГДЕ
    Контрагенты.Ссылка В (&Контрагент)}

Способ 2. Использование стандартных отборов СКД вместо параметров

Наиболее гибкий и рекомендуемый вариант для системы компоновки данных — отказ от жестких параметров в пользу встроенного механизма отборов.

Разберем по шагам, как перевести фильтрацию на отборы:

  1. Убираем из текста запроса жесткое условие ГДЕ Контрагенты.Ссылка = &Контрагент.
  2. Если требуется управлять доступностью полей отбора, используем конструкцию расширения компоновки данных:
    
    {ГДЕ
        Контрагенты.Ссылка.* КАК Контрагент}
    
  3. На вкладке Настройки в схеме компоновки данных переходим в раздел Отбор и добавляем поле Контрагент.
  4. Пользователь получает возможность выбирать любой вид сравнения: Равно, В списке, В группе из списка, В иерархии или вовсе отключать отбор снятием флажка.

Производительность: параметр запроса или отбор СКД?

Существует распространенное заблуждение, что параметры запроса работают быстрее отборов, так как отбор якобы фильтрует уже готовую таблицу данных в оперативной памяти. Выясним, как СКД работает на самом деле.

Если отбор установлен на верхнем уровне схемы (на уровне всего отчета), компоновщик данных автоматически оптимизирует результирующий SQL-запрос и встраивает условия отбора напрямую в секцию WHERE запроса к СУБД. Таким образом, фильтрация выполняется на стороне сервера базы данных, и никакой разницы в скорости выполнения по сравнению с параметрами нет.

Постобработка в памяти происходит только в тех случаях, когда отбор наложен на конкретную группировку или в нем используются вычисляемые поля, рассчитываемые после получения данных.

Ограничения при работе со списками

Рассмотрим технические ограничения, о которых необходимо помнить при передаче списков значений:

  1. Лимит параметров СУБД: При передаче списка через В (&Параметр) каждый элемент передается как отдельный параметр SQL-запроса. Большинство СУБД имеют лимит на количество параметров в одном запросе (например, MS SQL Server ограничивает их число до 2100). Передача десятков тысяч элементов в список значений приведет к ошибке СУБД.
  2. Нагрузка оператора В ИЕРАРХИИ: Использование иерархического отбора для больших списков может создавать тяжелые планы выполнения запросов из-за рекурсивного разворачивания дерева групп.
  3. Работа с большими массивами: Если требуется отобрать данные по списку из тысяч контрагентов, надежнее всего предварительно выгрузить их во временную таблицу и выполнить внутреннее соединение в основном запросе СКД.
← На главную