Как обратиться к вложенной табличной части в результате запроса 1С?

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

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

Способ 1. Обход вложенного результата запроса в цикле

Проанализируем типичную ситуацию: в тексте запроса выбраны поля документа и его табличная часть Автоработы. В этом случае поле Автоработы в каждой строке основного результата запроса будет иметь тип РезультатЗапроса. Это ключевой момент, который важно запомнить: это не массив и не строка, а полноценный результат, к которому нужно применить метод Выбрать().

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


// 1. Выполняем запрос и получаем основную выборку
РезЗапроса = НовыйЗапрос.Выполнить().Выбрать();

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

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

Способ 2. Использование соединений таблиц (ЛЕВОЕ СОЕДИНЕНИЕ)

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

Разберем преимущества этого подхода:

  1. Производительность: СУБД гораздо эффективнее обрабатывает одно соединение таблиц, чем множество вложенных выборок.
  2. Гибкость: Мы можем легко накладывать условия (ГДЕ) на поля табличной части и группировать их.
  3. Отсутствие ограничений: Платформа 1С позволяет использовать только один уровень вложенности через «скобки». С помощью соединений можно вытащить данные из любого количества табличных частей.

Пример «плоского» запроса с соединением:


ВЫБРАТЬ
    ЗаказНаряд.Номер КАК Номер,
    ЗаказНаряд.Дата КАК Дата,
    ЗаказНарядАвтоработы.Авторабота КАК Авторабота,
    ЗаказНарядАвтоработы.Сумма КАК Сумма
ИЗ
    Документ.ЗаказНаряд КАК ЗаказНаряд
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказНаряд.Автоработы КАК ЗаказНарядАвтоработы
        ПО ЗаказНаряд.Ссылка = ЗаказНарядАвтоработы.Ссылка
ГДЕ
    ЗаказНаряд.Контрагент = &Контрагент

Способ 3. Использование предложения ИТОГИ

Посмотрим на ситуацию, когда нам нужно и сохранить иерархию (Документ -> Строки), и обеспечить высокую скорость работы. Для этого идеально подходит предложение ИТОГИ. Мы используем плоский запрос (как в способе 2), но в конце добавляем группировку по ссылке на документ.

Проанализируем код обхода такого результата:


ТекстЗапроса = "
|ВЫБРАТЬ ...
|ИЗ Документ.ЗаказНаряд КАК ЗаказНаряд
|ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказНаряд.Автоработы КАК Автоработы ПО ...
|ИТОГИ ПО Ссылка";

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

Пока ВыборкаДокумент.Следующий() Цикл
    Сообщить("Заказ: " + ВыборкаДокумент.Ссылка);
    
    // Переходим к детальным записям (строкам ТЧ)
    ВыборкаСтрок = ВыборкаДокумент.Выбрать();
    Пока ВыборкаСтрок.Следующий() Цикл
        Сообщить("- Строка: " + ВыборкаСтрок.Авторабота);
    КонецЦикла;
КонецЦикла;

Работа с данными в памяти: Выгрузка в Таблицу значений или Дерево

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

Например, вызов РезЗапроса.Автоработы.Выгрузить() вернет объект ТаблицаЗначений. Это позволяет:

Если же вы используете ИТОГИ, весь результат запроса можно выгрузить в Дерево значений с помощью команды Результат.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам). Это особенно полезно при разработке форм, где данные должны отображаться в виде разворачивающихся узлов.

Важные нюансы и ограничения

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

  1. Пустые табличные части: Если у документа нет строк в табличной части, вложенная выборка все равно будет существовать как объект, но метод ВыборкаСтрок.Следующий() сразу вернет Ложь. Это избавляет от необходимости дополнительных проверок на Неопределено или Null.
  2. Память: Выгрузка вложенных таблиц через .Выгрузить() при обработке десятков тысяч документов может привести к быстрому переполнению оперативной памяти, так как в каждой ячейке колонки основной таблицы будет лежать целая вспомогательная таблица.
  3. Синтаксис псевдонимов: Во вложенном запросе (в скобках) всегда старайтесь задавать понятные псевдонимы через КАК. При обходе выборки вы будете обращаться именно к этим именам (например, ВыборкаСтрок.АвтоработаАртикул).

Таким образом, выбор метода зависит от конкретной задачи: для простых отчетов и небольших обработок отлично подойдет вложенная выборка (Способ 1), а для высоконагруженных систем или сложных выборок лучше использовать соединения и ИТОГИ.

← На главную