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

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

При работе с запросами в системе 1С:Предприятие программисты часто сталкиваются с задачей, когда из табличной части документа необходимо получить только одну строку. Это может быть самая первая позиция номенклатуры в заказе, первая строка состава услуги или любой другой реквизит, представляющий "заголовочную" информацию из ТЧ. Основная трудность заключается в том, что стандартная конструкция ВЫБРАТЬ ПЕРВЫЕ 1 работает на весь результат запроса целиком, а не на каждую группу строк (документ).

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

Проблема использования конструкции ВЫБРАТЬ ПЕРВЫЕ 1

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

Способ 1: Фильтрация по номеру строки (Простой вариант)

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

Проанализируем пример запроса:


ВЫБРАТЬ
    Товары.Ссылка КАК ДокументСсылка,
    Товары.Номенклатура КАК Номенклатура,
    Товары.Количество КАК Количество
ИЗ
    Документ.ПоступлениеТоваров.Товары КАК Товары
ГДЕ
    Товары.НомерСтроки = 1

Преимущества этого метода:

  1. Высокая скорость выполнения, так как нет сложных соединений.
  2. Простота написания и чтения кода.

Риски и нюансы:

Важно помнить, что в редких случаях в информационной базе может отсутствовать строка с номером 1. Это может произойти при некорректном программном заполнении ТЧ (например, если разработчик вручную установил номера строк через объектную технику и начал с 2), либо при специфических обменах данными, где строки переносятся с "дырами" в нумерации. Также, если документ пустой, он вообще не попадет в выборку.

Способ 2: Соединение с подзапросом через МИНИМУМ (Надежный вариант)

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

Разберем по шагам реализацию через ВНУТРЕННЕЕ СОЕДИНЕНИЕ:


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

В данном примере подзапрос формирует список уникальных ссылок на документы и соответствующих им минимальных номеров строк. Основная таблица соединяется с этим списком по двум полям, что позволяет отсечь все лишние строки ТЧ.

Способ 3: Включение документов без строк (ЛЕВОЕ СОЕДИНЕНИЕ)

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

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


ВЫБРАТЬ
    ПоступлениеТоваров.Ссылка КАК Ссылка,
    ЕСТЬNULL(Товары.Номенклатура, ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)) КАК Номенклатура
ИЗ
    Документ.ПоступлениеТоваров КАК ПоступлениеТоваров
ЛЕВОЕ СОЕДИНЕНИЕ (
    ВЫБРАТЬ
        ТЧ.Ссылка КАК Ссылка,
        МИНИМУМ(ТЧ.НомерСтроки) КАК НомерСтроки
    ИЗ
        Документ.ПоступлениеТоваров.Товары КАК ТЧ
    СГРУППИРОВАТЬ ПО
        ТЧ.Ссылка
) КАК МинимальныеСтроки
ПО ПоступлениеТоваров.Ссылка = МинимальныеСтроки.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваров.Товары КАК Товары
ПО МинимальныеСтроки.Ссылка = Товары.Ссылка 
    И МинимальныеСтроки.НомерСтроки = Товары.НомерСтроки

Использование функции ЕСТЬNULL позволяет корректно обработать ситуацию, когда у документа нет строк — в результате мы получим пустую ссылку вместо NULL, что удобнее для дальнейшей обработки или вывода в отчет.

Способ 4: Оптимизация через временные таблицы

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

Разберем алгоритм:

  1. Выбираем Ссылка и МИНИМУМ(НомерСтроки) во временную таблицу.
  2. Индексируем временную таблицу по полям связи.
  3. Соединяем временную таблицу с исходной табличной частью.

Пример кода:


ВЫБРАТЬ
    ТЧ.Ссылка КАК Ссылка,
    МИНИМУМ(ТЧ.НомерСтроки) КАК НомерСтроки
ПОМЕСТИТЬ ВТ_ПервыеСтроки
ИЗ
    Документ.ПоступлениеТоваров.Товары КАК ТЧ
СГРУППИРОВАТЬ ПО
    ТЧ.Ссылка
ИНДЕКСИРОВАТЬ ПО
    Ссылка,
    НомерСтроки
;

ВЫБРАТЬ
    ВТ.Ссылка,
    Товары.Номенклатура,
    Товары.Количество
ИЗ
    ВТ_ПервыеСтроки КАК ВТ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваров.Товары КАК Товары
ПО ВТ.Ссылка = Товары.Ссылка 
    И ВТ.НомерСтроки = Товары.НомерСтроки

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

Рекомендации по выбору метода

Подведем итоги нашего анализа:

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

← На главную