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

Превращение обычного массива в полноценную таблицу значений внутри запроса открывает широкие возможности для оптимизации. Вы получаете гибкость SQL-подобных операций прямо в контексте платформы. Это позволяет избежать циклических запросов и существенно снизить нагрузку на сервер баз данных при работе с большими объемами информации.

Концепция временных таблиц в языке запросов

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

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

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

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

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

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

Создание и заполнение ТаблицыЗначений

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

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

  • 📌 Создайте объект ТЗ = Новый ТаблицаЗначений().
  • 📌 Добавьте колонку ТЗ.Колонки.Добавить("Идентификатор", Тип("Ссылка.Номенклатура")).
  • 📌 В цикле вызывайте НоваяСтрока = ТЗ.Добавить() и присваивайте значения.
  • 📌 Убедитесь, что типы данных в коде совпадают с объявленными в колонках.

Существует нюанс с заполнением пустых значений. Если в вашем исходном массиве есть неопределенные значения (Null), их обработка зависит от настроек колонки. По умолчанию колонки допускают неопределенные значения, но для полей, участвующих в соединениях (JOIN), лучше явно контролировать этот аспект.

💡

Если вы передаете список кодов, а не ссылок, создавайте колонку типа Строка с соответствующей длиной. Это сэкономит память по сравнению с хранением полных ссылок.

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

Синтаксис запроса с параметром-таблицей

Текст запроса имеет специфическую структуру при работе с табличными параметрами. В секции ОПРЕДЕЛЕНИЯ вы должны явно указать тип параметра. Без этого указания система не поймет, как интерпретировать переданный объект, и выдаст ошибку компиляции текста запроса.

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

ВЫБРАТЬ

СправочникНоменклатура.Ссылка КАК Ссылка,

СправочникНоменклатура.Наименование КАК Наименование

ИЗ

Справочник.Номенклатура КАК СправочникНоменклатура

ВНУТРЕННЕЕ СОЕДИНЕНИЕ &МассивДанных КАК МассивДанные

ПО СправочникНоменклатура.Ссылка = МассивДанные.Идентификатор

Обратите внимание на использование псевдонимов. Параметр &МассивДанные получает алиас МассивДанные, к полям которого нужно обращаться именно через этот алиас. Прямое обращение к имени параметра в секции ВЫБРАТЬ без алиаса возможно, но может снизить читаемость кода.

⚠️ Внимание! Не используйте зарезервированные слова СУБД в качестве имен колонок внутри ТаблицыЗначений (например, "Order", "Group", "Select"). Это может вызвать конфликт при генерации SQL-кода платформой.

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

Почему иногда запрос не видит параметр?

Если вы забыли указать тип параметра в секции ОПРЕДЕЛЕНИЯ или передали в него объект другого типа (например, Массив вместо ТаблицыЗначений), компилятор запросов выдаст ошибку. Всегда проверяйте соответствие типов при отладке.

Оптимизация производительности и индексы

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

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

Метод фильтрации Объем данных Скорость выполнения Нагрузка на память
Оператор IN До 500 элементов Высокая Низкая
ТаблицаЗначений (JOIN) 1 000 - 50 000 Средняя/Высокая Средняя
Временная таблица СУБД Более 50 000 Зависит от диска Высокая (диск)
Цикл по элементам Любой Низкая Минимальная

Для ускорения выборки рекомендуется добавлять индексы в саму ТаблицуЗначений перед передачей в запрос. Метод Индексы.Добавить() позволяет указать поля, по которым будет происходить соединение. Это аналог создания индекса во временной таблице на стороне SQL сервера.

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

Обработка результатов и исключительные ситуации

Результатом выполнения такого запроса является объект ВыборкаИзРезультатаЗапроса. Вы можете iterating по нему стандартным циклом Для каждого ... Из ... Цикл. Структура результата будет соответствовать секции ВЫБРАТЬ вашего текста запроса.

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

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

☑️ Проверка перед запуском

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

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

Сравнение с альтернативными методами

Помимо ТаблицыЗначений, разработчики часто используют временные таблицы на стороне СУБД (ВРЕМЕННАЯ ТАБЛИЦА в тексте запроса). Этот метод подходит для очень больших данных, которые не помещаются в оперативную память или должны быть доступны в нескольких последовательных запросах.

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

⚠️ Внимание! Интерфейсы и возможности платформы могут обновляться. В новых версиях 1С алгоритмы оптимизации запросов меняются. Всегда сверяйте поведение системы с официальными выпусками новостей технологии для вашей версии платформы.

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

💡

Использование ТаблицыЗначений как параметра запроса — это баланс между скоростью работы в памяти и гибкостью SQL-фильтрации, идеальный для списков до 10-20 тысяч элементов.

Часто задаваемые вопросы

Можно ли передать обычный Массив в запрос вместо ТаблицыЗначений?

Нет, напрямую передать объект типа Массив в параметр запроса нельзя. Движок запросов ожидает структурированные данные с именованными колонками. Вам необходимо предварительно конвертировать массив в объект ТаблицаЗначений.

Каков максимальный размер ТаблицыЗначений для передачи в запрос?

Жесткого ограничения со стороны платформы нет, все лимитируется доступной оперативной памятью сервера или клиента. Однако на практике при объеме свыше 50-100 тысяч строк производительность может падать, и стоит рассмотреть временные таблицы СУБД.

Как передать несколько колонок в параметре?

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

Работает ли этот метод в управляемых формах?

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