Как вывести данные первой строки табличной части в динамическом списке 1С

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

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

Проблема выбора данных из подчиненных таблиц

Динамический список в 1С работает на основе системы компоновки данных (СКД). Его главная задача — быстро выбирать данные из основной таблицы (например, Документ.РеализацияТоваровУслуг). Однако табличные части хранятся в отдельных физических таблицах базы данных. Если мы просто добавим таблицу ТЧ в запрос без ограничений, система «размножит» строки документа в списке: на каждую строку ТЧ появится отдельная строка в списке документов. Чтобы этого избежать, нам нужно гарантировать, что из таблицы ТЧ для каждого документа будет выбрана ровно одна запись — первая.

Способ 1: Левое соединение по номеру строки

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

Рассмотрим пример запроса:


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

Почему это работает? Мы используем ЛЕВОЕ СОЕДИНЕНИЕ, чтобы документы, у которых вообще нет строк в табличной части, все равно отображались в списке (с пустым значением в колонке номенклатуры). Условие ПродажаТовары.НомерСтроки = 1 жестко ограничивает выборку из ТЧ только первой записью.

Почему нельзя использовать ПЕРВЫЕ 1 в основном запросе?

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

Способ 2: Использование агрегатных функций для надежности

Хотя первый способ надежен в 99% случаев, иногда в результате программных обработок или некорректных обменов данными нумерация строк может начинаться не с единицы. Чтобы сделать решение максимально «неубиваемым», мы можем использовать минимальный номер строки, который фактически существует в базе. Для этого воспользуемся вложенным запросом.

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

  1. Сначала мы создаем вложенную таблицу, где для каждой ссылки документа находим минимальный НомерСтроки.
  2. Затем мы соединяем основную таблицу документов с этим вложенным запросом.
  3. Вторым соединением мы получаем данные из ТЧ, соответствующие найденному минимальному номеру.

Пример реализации такого запроса:


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

Такой подход гарантирует получение данных, даже если в ТЧ есть только строки с номерами 5, 10 и так далее.

Производительность и индексация

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

Архитектурная альтернатива: Денормализация

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

Посмотрим на этот процесс:

  1. Вы добавляете в сам документ новый реквизит, например, ТоварДляСписка.
  2. В процедуре ПередЗаписью или ПриЗаписи документа в модуле объекта вы программно берете значение из первой строки ТЧ и записываете его в этот реквизит.
  3. В динамическом списке вы просто выводите этот реквизит без всяких соединений.

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

Особенности настройки в интерфейсе

При редактировании запроса в конструкторе динамического списка не забудьте проверить свойство «Основная таблица». Она должна быть установлена в значение Документ.РеализацияТоваровУслуг (или другой ваш документ). Если основная таблица не указана, платформа не сможет автоматически применять фильтры, а также могут возникнуть проблемы с правами доступа (RLS).

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

ЕСТЬNULL(ПродажаТовары.Номенклатура.Наименование, "—") КАК НоменклатураТекст

Резюме

Для большинства задач достаточно использовать Левое соединение по НомерСтроки = 1. Это стандартный, читаемый и эффективный способ. К более сложным конструкциям с агрегатными функциями или денормализацией данных стоит переходить только в случае специфических требований к надежности или при проблемах с производительностью на очень больших базах данных.

← На главную