Как выгрузить данные из выборки запроса в таблицу значений

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

В процессе разработки на платформе 1С:Предприятие 8 программисты часто сталкиваются с необходимостью преобразовать данные, полученные из запроса, в объект ТаблицаЗначений. Однако стандартный метод Выгрузить() работает не всегда так, как ожидает начинающий разработчик, особенно когда дело касается обхода результата по группировкам. Разберем подробно, почему возникает путаница между выборкой и результатом запроса, и какими способами можно получить таблицу значений в различных ситуациях.

Различие между Результатом запроса и Выборкой

Проанализируем архитектуру работы с запросами в 1С. Когда мы вызываем метод Запрос.Выполнить(), система возвращает объект типа РезультатЗапроса. Именно у этого объекта есть встроенный метод Выгрузить(), который позволяет моментально получить всю таблицу или дерево значений.

Ситуация меняется, когда мы начинаем использовать метод Выбрать(). Этот метод создает объект ВыборкаИзРезультатаЗапроса. Выборка — это динамический механизм последовательного чтения строк. У нее нет метода Выгрузить(). Попытка вызвать его приведет к ошибке исполнения. Это фундаментальное ограничение: выборка предназначена для обхода записей «вперед», а не для хранения их в памяти целиком.

Рассмотрим подробнее три основных способа решения этой задачи в зависимости от ваших целей.

Способ 1: Ручное наполнение Таблицы значений при обходе выборки

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

Разберем этот процесс по шагам:

  1. Создаем новый экземпляр ТаблицаЗначений.
  2. Определяем колонки таблицы, соответствующие полям нашего запроса.
  3. Запускаем цикл Пока Выборка.Следующий().
  4. Для каждой итерации добавляем новую строку и копируем в нее данные.

Посмотрим на пример кода, реализующего этот алгоритм:


// Предположим, РезВыборкаПоКод6 — это наша выборка из запроса
ТЗ_Результат = Новый ТаблицаЗначений;
// Добавляем необходимые колонки вручную
ТЗ_Результат.Колонки.Добавить("Номенклатура");
ТЗ_Результат.Колонки.Добавить("Количество");
ТЗ_Результат.Колонки.Добавить("Сумма");

Пока РезВыборкаПоКод6.Следующий() Цикл
    НоваяСтрока = ТЗ_Результат.Добавить();
    // Используем эффективный метод ЗаполнитьЗначенияСвойств
    ЗаполнитьЗначенияСвойств(НоваяСтрока, РезВыборкаПоКод6);
КонецЦикла;

Выясним причину использования ЗаполнитьЗначенияСвойств. Этот метод работает значительно быстрее, чем ручное присвоение значений каждой колонке (например, НоваяСтрока.Номенклатура = РезВыборкаПоКод6.Номенклатура), так как сопоставление имен полей происходит на уровне платформы.

Способ 2: Предварительная выгрузка и фильтрация (Метод Скопировать)

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

Проанализируем ситуацию: у нас есть запрос с группировкой по «Складу». Мы хотим для каждого склада получить отдельную ТЗ с его товарами. Рассмотрим реализацию:


// 1. Сначала выгружаем весь результат запроса в одну общую ТЗ
ПолнаяТЗ = РезультатЗапроса.Выгрузить();

// 2. Делаем выборку по группировке Склад
ВыборкаСклад = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаСклад.Следующий() Цикл
    // 3. Для каждой группировки создаем структуру отбора
    ПараметрыОтбора = Новый Структура("Склад", ВыборкаСклад.Склад);
    
    // 4. Получаем таблицу значений только по текущему складу
    ТЗ_ТекущегоСклада = ПолнаяТЗ.Скопировать(ПараметрыОтбора);
    
    // Теперь ТЗ_ТекущегоСклада содержит данные только по конкретному складу
КонецЦикла;

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

Способ 3: Использование Дерева значений для сохранения иерархии

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

Посмотрим на пример выгрузки структуры иерархии:


// Вместо обхода выборкой, сразу выгружаем в дерево
ДеревоРезультата = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);

// Теперь мы можем обращаться к строкам первого уровня (верхняя группировка)
Для Каждого СтрокаГруппы1 Из ДеревоРезультата.Строки Цикл
    // Содержимое подчиненных строк (следующая группировка) доступно в коллекции .Строки
    Для Каждого СтрокаГруппы2 Из СтрокаГруппы1.Строки Цикл
        // Обработка данных
    КонецЦикла;
КонецЦикла;

Важный момент: при выгрузке в дерево значений 1С автоматически создает иерархическую структуру, где каждый узел содержит данные полей группировки и коллекцию вложенных строк. Это наиболее «чистый» способ работы с иерархическими данными запроса без использования объекта ВыборкаИзРезультатаЗапроса.

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

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

Сформулируем основные правила выбора метода:

  1. Если нужно просто перебрать записи для расчетов — используйте ВыборкаИзРезультатаЗапроса (через Выбрать() и Следующий()). Это самый экономный по памяти способ.
  2. Если данные нужно передать на форму или в функцию, которая принимает только таблицы — используйте РезультатЗапроса.Выгрузить().
  3. Если вы уже находитесь в цикле выборки и «вдруг» понадобилось превратить остаток данных в таблицу — используйте Способ 1 (ручное наполнение с ЗаполнитьЗначенияСвойств).
  4. Если требуется работа с итогами и иерархией — используйте ДеревоЗначений.

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

← На главную