В процессе разработки сложных прикладных решений на платформе 1С:Предприятие 8 программисты часто сталкиваются с необходимостью фильтрации данных по большому списку значений. Стандартный подход с использованием оператора IN или перечисления через запятую имеет серьезные ограничения по длине строки запроса и производительности. Когда список элементов достигает сотен или тысяч позиций, прямой подстановкой этих значений в текст запроса не обойтись.

Эффективным решением этой проблемы является передача таблицы значений в качестве параметра запроса. Этот механизм позволяет формировать динамические списки в коде управляемого приложения или сервера, а затем использовать их внутри языка запросов как полноценные виртуальные таблицы. Такой подход не только снимает ограничения на размер запроса, но и существенно оптимизирует работу СУБД, позволяя использовать механизмы временных таблиц.

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

Концепция параметра типа Таблица значений

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

Использование данного механизма критически важно при реализации отчетов с множественным отбором или при обработке данных, полученных через внешние интерфейсы. Например, если пользователь выбирает в интерфейсе 500 номенклатурных позиций для анализа остатков, передача этого списка через параметр-таблицу является единственно верным архитектурным решением. Прямая конкатенация строк в тексте запроса в таком случае приведет к ошибке выполнения или критическому падению производительности.

Важно понимать, что структура таблицы-параметра должна быть заранее определена. Вы не можете передать "абстрактную" таблицу; она должна иметь конкретные колонки с указанными типами данных. Эти типы должны соответствовать типам полей в основной выборке запроса, с которыми вы планируете проводить соединения или сравнения. Несоблюдение этого правила вызовет ошибку несовместимости типов на этапе компиляции запроса.

⚠️ Внимание: Имена колонок в таблице-параметре и в основной таблице базы данных могут отличаться, но их типы данных должны быть совместимы. При выполнении соединения ЛЕВОЕ СОЕДИНЕНИЕ или условия В платформа попытается привести типы, что может замедлить выполнение.

💡

Всегда создавайте колонки в таблице значений с тем же типом, что и в основной таблице БД, чтобы избежать неявного приведения типов и использования индексов.

Создание и заполнение таблицы в коде

Процесс подготовки данных начинается в программном модуле, обычно перед вызовом объекта запроса. Первым шагом является создание нового экземпляра объекта ТаблицаЗначений. После создания необходимо описать его структуру, добавив нужные колонки. Имена колонок лучше делать лаконичными, но понятными, так как они будут использоваться в тексте запроса.

Для добавления колонок используется метод Колонки.Добавить. В качестве аргумента передается имя колонки и тип значения. Тип можно задать строкой (например, "Число(15,2)") или получить через встроенную функцию Тип(). Если вы планируете соединять эту таблицу со справочником "Номенклатура", то колонка должна иметь тип СправочникСсылка.Номенклатура.

ТЗПараметр = Новый ТаблицаЗначений;

ТЗПараметр.Колонки.Добавить("Номенклатура", Тип("СправочникСсылка.Номенклатура"));

ТЗПараметр.Колонки.Добавить("Характеристика", Тип("СправочникСсылка.ХарактеристикиНоменклатуры"));

После описания структуры таблицу необходимо заполнить данными. Это можно сделать построчно, добавляя новую строку и присваивая значения полям, либо использовать метод ЗагрузитьКолонки для массового переноса данных из массива или другого табличного документа. Важно убедиться, что в таблицу не попали пустые значения, если логика вашего запроса этого не предполагает, хотя сама платформа допускает наличие NULL в параметрах.

☑️ Алгоритм подготовки параметра

Выполнено: 0 / 4

Синтаксис использования в тексте запроса

В языке запросов 1С таблица-параметр используется как обычное имя таблицы. Вам не нужно применять какие-либо специальные префиксы или функции для доступа к ней. Достаточно указать имя параметра, которое вы задали в коде при установке значения, в секции ИЗ или в условии ГДЕ.

Существует два основных сценария использования. Первый — это фильтрация основного запроса по списку значений из параметра с помощью оператора В. Второй, более производительный для больших объемов данных, — это явное соединение (СОЕДИНЕНИЕ) основной таблицы с таблицей-параметром. Выбор метода зависит от объема данных и конкретной задачи.

Рассмотрим пример использования оператора В. В этом случае мы выбираем документы, где ссылка на контрагента содержится в нашей параметрической таблице. Синтаксически это выглядит очень компактно и читаемо. Платформа сама оптимизирует такой запрос, преобразуя его во внутреннее соединение, если это целесообразно.

ВЫБРАТЬ

Продажи.Ссылка КАК Ссылка,

Продажи.Дата КАК Дата

ИЗ

Документ.РеализацияТоваровУслуг КАК Продажи

ГДЕ

Продажи.Контрагент В (&ТаблицаКонтрагентов)

Однако для сложных аналитических выборок предпочтительнее использовать конструкцию ЛЕВОЕ СОЕДИНЕНИЕ. Это позволяет не только отфильтровать данные, но и подтянуть дополнительные атрибуты из параметра, если они там есть. Например, вы можете передать таблицу с номенклатурой и желаемыми ценами, а затем сравнить их с фактическими ценами в базе.

Оптимизация больших соединений

Если таблица параметров содержит более 1000 строк, использование явного СОЕДИНЕНИЯ часто работает быстрее, чем оператор В, так как позволяет СУБД лучше использовать индексы временных таблиц.

Сравнение методов: оператор В и СОЕДИНЕНИЕ

Выбор между оператором В и конструкцией СОЕДИНЕНИЕ влияет на план выполнения запроса сервером баз данных. Оператор В удобен для простых фильтров, когда нужно просто проверить вхождение значения в список. Он интуитивно понятен разработчикам и требует меньше кода. Однако при очень больших списках (десятки тысяч записей) некоторые СУБД могут менее эффективно строить план выполнения для такого оператора по сравнению с джойнами.

Использование ЛЕВОЕ СОЕДИНЕНИЕ дает больше гибкости. Вы можете отфильтровать записи, у которых нет соответствия в таблице параметров (проверка на ЕСТЬ NULL), или, наоборот, оставить только совпадающие (внутреннее соединение). Кроме того, этот метод позволяет передавать в запросе не просто список ссылок, а сложные структуры с дополнительными коэффициентами, флагами или приоритетами.

Ниже приведена таблица, сравнивающая основные характеристики двух подходов в различных сценариях использования:

Критерий Оператор В (IN) СОЕДИНЕНИЕ (JOIN)
Читаемость кода Высокая, лаконичная запись Средняя, требует описания условий связи
Производительность (малые списки) Одинаковая Одинаковая
Производительность (большие списки) Может снижаться Стабильно высокая
Возможность передачи доп. данных Нет, только список значений Да, любые колонки таблицы

При разработке высоконагруженных подсистем рекомендуется проводить тестирование обоих вариантов на реальных объемах данных вашей базы. В большинстве случаев для списков до 500 элементов разница незаметна, но при масштабировании системы правильный выбор метода становится критичным.

📊 Какой метод вы чаще используете для фильтрации по списку?
Оператор В
Внутреннее соединение
Левое соединение
Зависит от задачи

Обработка пустых параметров и типизация

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

Для решения этой задачи используется проверка на заполненность таблицы перед формированием запроса. В коде 1С это делается через свойство Количество(). Если таблица пуста, параметр запросу можно не передавать вовсе, либо передавать специальное значение, которое обработается в тексте запроса через конструкцию ЕСТЬ NULL или логику ЕСЛИ внутри запроса (если используется диалект, поддерживающий это).

Типизация играет ключевую роль в безопасности и стабильности. Если в колонку таблицы значений типа Число попытаться записать строку, возникнет ошибка выполнения. Также стоит избегать использования типа Строка неограниченной длины для хранения ссылок на объекты, так как это мешает оптимизатору запросов. Всегда используйте конкретные типы ссылок или перечислений.

⚠️ Внимание: Никогда не используйте тип "Любой" или "Строка" для хранения ссылок на объекты базы данных в параметрах таблицы. Это приведет к полному сканированию таблиц и игнорированию индексов.

Производительность и временные таблицы

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

Для минимизации затрат старайтесь передавать в параметре только необходимые колонки. Не нужно тащить в таблицу значений все реквизиты объекта, если для фильтрации нужен только код или ссылка. Лишние данные увеличивают объем передаваемой информации и время на запись во временное хранилище.

В распределенных информационных базах (РИБ) или при работе через тонкий клиент с большим количеством данных передача объемной таблицы значений может занять заметное время из-за сетевого взаимодействия. В таких случаях целесообразно рассмотреть альтернативные варианты, например, запись данных во временное хранилище на сервере заранее, если архитектура приложения это позволяет.

💡

Передача таблицы значений — это компромисс между гибкостью фильтрации и затратами на создание временных таблиц. Оптимизируйте структуру передаваемых данных.

Можно ли передать таблицу значений через внешнюю обработку?

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

Каков максимальный размер таблицы параметров?

Технического жесткого ограничения на количество строк в таблице значений нет, оно ограничено доступной оперативной памятью процесса сервера 1С и настройками СУБД на размер временных таблиц. Однако на практике передача таблиц более 100 000 строк может существенно замедлить работу системы.

Что делать, если типы в параметре и запросе не совпадают?

Если типы несовместимы (например, Число и Строка), запрос не выполнится и выдаст ошибку компиляции. Если типы совместимы, но различаются (например, СправочникСсылка.Номенклатура и СправочникСсылка.Номенклатура.ТабличнаяЧасть), может произойти неявное приведение, что негативно скажется на производительности. Всегда приводите типы явно в коде перед записью в таблицу.

Можно ли использовать таблицу значений в СКД без программирования?

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