При разработке отчетов на системе компоновки данных (СКД) разработчики часто сталкиваются с задачей выбора нескольких значений одного объекта — например, нескольких контрагентов, номенклатурных позиций или складов. Если просто включить флаг Доступен список значений на вкладке «Параметры», платформа может выдать ошибку о сравнении несовместимых типов или строк неограниченной длины. Разберем причины возникновения этой ошибки и рассмотрим корректные способы ее решения.
Проанализируем исходную ситуацию. В тексте запроса жестко прописано условие равенства:
ГДЕ
Контрагенты.Ссылка = &Контрагент
Оператор равенства = в языке запросов 1С рассчитан исключительно на работу с одиночным значением (скалярным типом, например конкретной ссылкой СправочникСсылка.Контрагенты). Когда в настройках параметра СКД мы устанавливаем флаг Доступен список значений, тип передаваемого значения трансформируется в коллекцию (объект СписокЗначений или массив). При попытке сравнить ссылку со списком СУБД сообщает о несовместимости типов данных.
Для исправления ситуации можно использовать несколько подходов в зависимости от требований к отчету и удобства пользователей.
Если необходимо оставить именно параметр СКД, изменим оператор сравнения в секции ГДЕ. Для работы с коллекциями значений в языке запросов 1С применяются операторы В и В ИЕРАРХИИ.
В: проверяет вхождение ссылки в указанный список элементов:
ГДЕ
Контрагенты.Ссылка В (&Контрагент)
В ИЕРАРХИИ: подходит, если в списке могут присутствовать группы справочника, и требуется получить данные как по самим группам, так и по всем их дочерним элементам:
ГДЕ
Контрагенты.Ссылка В ИЕРАРХИИ (&Контрагент)
Важное замечание: если условие прописано жестко в основном тексте запроса без расширения СКД, параметр &Контрагент станет обязательным к заполнению. Если пользователь оставит список пустым, запрос не вернет строк либо завершится с ошибкой.
Чтобы условие накладывалось только тогда, когда параметр действительно заполнен пользователем, воспользуемся синтаксисом расширения языка запросов компоновки данных (фигурные скобки):
{ГДЕ
Контрагенты.Ссылка В (&Контрагент)}
Наиболее гибкий и рекомендуемый вариант для системы компоновки данных — отказ от жестких параметров в пользу встроенного механизма отборов.
Разберем по шагам, как перевести фильтрацию на отборы:
ГДЕ Контрагенты.Ссылка = &Контрагент.
{ГДЕ
Контрагенты.Ссылка.* КАК Контрагент}
Контрагент.Существует распространенное заблуждение, что параметры запроса работают быстрее отборов, так как отбор якобы фильтрует уже готовую таблицу данных в оперативной памяти. Выясним, как СКД работает на самом деле.
Если отбор установлен на верхнем уровне схемы (на уровне всего отчета), компоновщик данных автоматически оптимизирует результирующий SQL-запрос и встраивает условия отбора напрямую в секцию WHERE запроса к СУБД. Таким образом, фильтрация выполняется на стороне сервера базы данных, и никакой разницы в скорости выполнения по сравнению с параметрами нет.
Постобработка в памяти происходит только в тех случаях, когда отбор наложен на конкретную группировку или в нем используются вычисляемые поля, рассчитываемые после получения данных.
Рассмотрим технические ограничения, о которых необходимо помнить при передаче списков значений:
В (&Параметр) каждый элемент передается как отдельный параметр SQL-запроса. Большинство СУБД имеют лимит на количество параметров в одном запросе (например, MS SQL Server ограничивает их число до 2100). Передача десятков тысяч элементов в список значений приведет к ошибке СУБД.В ИЕРАРХИИ: Использование иерархического отбора для больших списков может создавать тяжелые планы выполнения запросов из-за рекурсивного разворачивания дерева групп.