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

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

В практике разработки на платформе 1С:Предприятие часто возникает задача получить данные не из всей табличной части, а из конкретной строки. Если во встроенном языке это решается простым обращением по индексу (например, Объект.Товары[0].Цена), то в языке запросов прямого доступа к строке по индексу не существует. Однако есть несколько проверенных способов реализовать эту логику. В этой статье мы подробно разберем, как «выцепить» нужную строку в запросе, проанализируем нюансы нумерации и рассмотрим современные возможности платформы.

Метод 1: Классическое левое соединение по номеру строки

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

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


ВЫБРАТЬ
    ДокументПродажа.Ссылка КАК Ссылка,
    ДокументПродажаТовары.Номенклатура КАК НоменклатураВторойСтроки
ИЗ
    Документ.Продажа КАК ДокументПродажа
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.Продажа.Товары КАК ДокументПродажаТовары
        ПО ДокументПродажа.Ссылка = ДокументПродажаТовары.Ссылка
            И ДокументПродажаТовары.НомерСтроки = 2

Важный нюанс нумерации: Обратите внимание, что в табличных частях 1С поле НомерСтроки начинается с 1. Если в коде вы привыкли работать с индексами (которые начинаются с 0), то для запроса всегда прибавляйте единицу. Как правильно заметили участники обсуждения, формула соответствия выглядит так: НомерСтроки = Индекс + 1. Если вы передаете номер строки как параметр, убедитесь, что передаете именно НомерСтроки, а не индекс.

Метод 2: Динамическое определение номера строки в самом запросе

Иногда номер строки не является фиксированным (как «2» в примере выше), а вычисляется в ходе выполнения самого запроса. В этом случае мы можем использовать вычисляемое поле для связи. Давайте посмотрим на пример, где номер строки определяется каким-либо условием в основном запросе:


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

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

Метод 3: Использование оконных функций (ПОРЯДКОВЫЙ_НОМЕР)

Начиная с версии платформы 8.3.20, разработчикам стали доступны оконные функции. Это кардинально меняет подход к работе с очередностью строк. Функция ПОРЯДКОВЫЙ_НОМЕР() позволяет пронумеровать строки заново по любому критерию, не полагаясь на физическое поле НомерСтроки.

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

  1. Создаем вложенный запрос или временную таблицу, где нумеруем строки с помощью ПОРЯДКОВЫЙ_НОМЕР().
  2. В основном запросе накладываем фильтр на полученный номер.

Пример реализации:


ВЫБРАТЬ
    Подзапрос.Ссылка,
    Подзапрос.Номенклатура,
    Подзапрос.НоваяОчередность
ИЗ
    (ВЫБРАТЬ
        ТЧ.Ссылка КАК Ссылка,
        ТЧ.Номенклатура КАК Номенклатура,
        ПОРЯДКОВЫЙ_НОМЕР() ОБРАБОТКА НАД (УПОРЯДОЧИТЬ ПО ТЧ.Цена УБЫВ) КАК НоваяОчередность
    ИЗ
        Документ.РеализацияТоваровУслуг.Товары КАК ТЧ) КАК Подзапрос
ГДЕ
    Подзапрос.НоваяОчередность = 1 // Получаем самую дорогую позицию

Метод 4: Работа с не записанными данными (Таблица Значений)

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

Решение — передать табличную часть в запрос как параметр типа ТаблицаЗначений. Рассмотрим алгоритм:

  1. Выгружаем табличную часть: ТЗ = ЭтотОбъект.Товары.Выгрузить();.
  2. Важно: Если в ТЗ нет колонки НомерСтроки (она не всегда выгружается явно), добавьте её или используйте индекс.
  3. Передаем ТЗ в запрос: Запрос.УстановитьПараметр("ТаблицаТовары", ТЗ);.

Текст запроса в этом случае будет работать с временной таблицей, созданной из параметра:


ВЫБРАТЬ
    ВременнаяТЗ.Номенклатура
ИЗ
    &ТаблицаТовары КАК ВременнаяТЗ
ГДЕ
    ВременнаяТЗ.НомерСтроки = &НужныйНомер

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

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

Подводя итог, можно сказать, что выбор метода зависит от версии вашей платформы и конкретной бизнес-логики. Для старых конфигураций идеальным остается Левое соединение, а для современных систем на базе 8.3.20+ лучше использовать Оконные функции, так как они дают гораздо больше гибкости в управлении порядком строк.

← На главную