Как извлечь и обработать вложенную таблицу (выборку) из результата запроса в 1С

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

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

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

Разберемся в терминологии: Вложенный запрос vs Вложенная выборка

Прежде чем переходить к решению, нам необходимо четко разграничить два понятия, которые часто путают начинающие разработчики. От этого зависит понимание того, что именно мы пытаемся «вытащить».

  1. Вложенный запрос: Это запрос, который описывается в секции ИЗ или ГДЕ. Он выступает как временный источник данных для основного запроса. Результат такого запроса не виден в ячейках итоговой выборки — он просто помогает сформировать общую таблицу.
  2. Вложенная выборка: Это подзапрос, помещенный непосредственно в секцию ВЫБРАТЬ. Именно он создает структуру, при которой в каждой строке основного результата лежит еще одна маленькая таблица.

Рассмотрим пример вложенной выборки, которая и вызывает описываемую проблему:


ВЫБРАТЬ
    Реализация.Ссылка КАК Документ,
    (ВЫБРАТЬ
        Товары.Номенклатура,
        Товары.Количество
    ИЗ
        Документ.РеализацияТоваровУслуг.Товары КАК Товары
    ГДЕ
        Товары.Ссылка = Реализация.Ссылка) КАК СоставТоваров
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация

В данном случае поле СоставТоваров будет содержать объект типа ВыборкаИзРезультатаЗапроса. Рассмотрим, как с этим работать.

Способ 1. Программный обход вложенной выборки в цикле

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

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


Результат = Запрос.Выполнить();
ВыборкаДокументов = Результат.Выбрать();

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

Важный момент: Поле СоставТоваров в данном контексте ведет себя как объект РезультатЗапроса, у которого есть свой метод Выбрать(). Именно это позволяет нам входить на уровень глубже.

Способ 2. Как увидеть данные в отладчике

Часто разработчики жалуются, что при попытке посмотреть значение такого поля в отладчике (через F2 или в окне вычисления выражений) они видят техническое описание объекта, но не сами данные. Чтобы визуализировать «таблицу внутри поля», выполним следующие шаги:

  1. Остановим исполнение кода на строке, где выборка уже получена (после метода Следующий()).
  2. В окне «Вычислить выражение» введем: ВыборкаДокументов.СоставТоваров.Выгрузить() (поможет инструмент для пошаговой отладки кода 1С).
  3. Нажмем F2 на полученном результате.

Метод Выгрузить() принудительно преобразует объект ВыборкаИзРезультатаЗапроса в привычную Таблицу Значений. Только в этом случае вы сможете увидеть колонки и строки в удобном табличном виде. Без вызова Выгрузить() отладчик показывает лишь оболочку итератора.

Способ 3. Оптимальный подход через Временные Таблицы

Использование подзапросов в секции ВЫБРАТЬ (вложенных выборок) считается плохой практикой с точки зрения производительности, особенно если данных много. СУБД вынуждена выполнять отдельный микро-запрос для каждой строки основного результата. Разберем более правильный архитектурный подход — использование временных таблиц.

Проанализируем ситуацию: вместо того чтобы «вкладывать» таблицу товаров в каждую строку документов, мы можем подготовить данные заранее. Рассмотрим шаги:

  1. Поместим данные из табличной части документов во временную таблицу.
  2. Проиндексируем ее по ссылке для быстрого поиска.
  3. В итоговом запросе соединим основную таблицу документов с этой временной таблицей.

// Шаг 1: Создаем временную таблицу товаров
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;

Запрос.Текст = 
"ВЫБРАТЬ
|   ТЧ.Ссылка КАК ДокументСсылка,
|   ТЧ.Номенклатура,
|   ТЧ.Количество
|ПОМЕСТИТЬ ВТ_Товары
|ИЗ
|   Документ.РеализацияТоваровУслуг.Товары КАК ТЧ
|ИНДЕКСИРОВАТЬ ПО
|   ДокументСсылка;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|   Реализация.Ссылка КАК Документ,
|   ВТ_Товары.Номенклатура,
|   ВТ_Товары.Количество
|ИЗ
|   Документ.РеализацияТоваровУслуг КАК Реализация
|   ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Товары КАК ВТ_Товары
|   ПО Реализация.Ссылка = ВТ_Товары.ДокументСсылка";

Результат = Запрос.Выполнить();

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

Почему возникают ошибки при связях во вложенных запросах?

Разберем типичную ситуацию: программист пытается сделать ЛЕВОЕ СОЕДИНЕНИЕ внутри вложенного запроса, который сам находится в секции ВЫБРАТЬ. Это часто приводит к ошибкам компиляции запроса. Выясним причину:

Во вложенной выборке (внутри скобок в блоке ВЫБРАТЬ) нельзя обращаться к таблицам, которые не определены внутри этих же скобок, если только вы не используете корреляционную связь через ГДЕ. Платформа 1С строго ограничивает область видимости таблиц. Если вам нужно сложное соединение нескольких таблиц, чтобы получить «вложенный результат», лучше отказаться от вложенных выборок в пользу обычного плоского запроса с последующей группировкой данных в ТаблицеЗначений или ДеревеЗначений на стороне встроенного языка.

Резюме

Выяснив причину появления «Таблицы значений» в поле запроса, мы понимаем, что это удобный, но ресурсоемкий инструмент. Для работы с ним:

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

← На главную