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

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

При разработке отчетов или обработок на платформе «1С:Предприятие 8» часто возникает задача: необходимо вывести список документов и напротив каждого из них поставить признак (флаг), который сообщает, удовлетворяет ли хотя бы одна строка в его табличной части определенному критерию. Типичный пример — проверка, содержит ли документ определенную номенклатуру или услугу. Давайте подробно разберем, как это реализовать эффективно и избежать типичных ошибок при работе с левыми соединениями и составными типами данных.

Проблема «размножения» строк при соединении с табличной частью

Первое, с чем мы сталкиваемся при простом левом соединении документа с его табличной частью — это дублирование записей. Если документ содержит 10 строк в табличной части, то после ЛЕВОЕ СОЕДИНЕНИЕ в итоговой выборке мы получим 10 строк для этого документа. Если наша цель — получить одну строку на один документ с признаком «Истина/Ложь», обычное соединение без агрегации нам не подойдет. Проанализируем, как решить эту задачу правильно.

Решение через агрегатные функции и группировку

Самый распространенный и надежный способ — использование функции МАКСИМУМ в сочетании с конструкцией ВЫБОР. Рассмотрим пример кода, который позволяет пристегнуть признак наличия записи к шапке документа:


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

СГРУППИРОВАТЬ ПО
    Документ.Ссылка,
    Документ.Номер,
    Документ.Дата

Разберем этот запрос по шагам. Почему мы используем именно такие конструкции?

  1. ЛЕВОЕ СОЕДИНЕНИЕ: Оно гарантирует, что в результат попадут все документы из шапки, даже если их табличная часть пуста или ни одна строка не соответствует условию.
  2. Конструкция ВЫБОР: Мы преобразуем наличие подходящей строки в числовое значение 1, а неподходящей — в 0.
  3. Функция МАКСИМУМ: Так как мы группируем результат по ссылке документа, МАКСИМУМ выберет единицу, если в документе была хотя бы одна подходящая строка. Если подходящих строк нет, максимум среди нулей будет равен 0.
  4. СГРУППИРОВАТЬ ПО: Этот блок необходим для того, чтобы «схлопнуть» все строки табличной части обратно в одну строку документа.

Оптимизация через использование временных таблиц

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


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

// Теперь соединяем основной список с нашей временной таблицей
ВЫБРАТЬ
    Документ.Ссылка,
    ВЫБОР
        КОГДА ВТ_ДокументыСУсловием.Ссылка ЕСТЬ NULL
            ТОГДА ЛОЖЬ
        ИНАЧЕ ИСТИНА
    КОНЕЦ КАК ФлагНаличия
ИЗ
    Документ.РеализацияТоваровУслуг КАК Документ
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ДокументыСУсловием КАК ВТ_ДокументыСУсловием
        ПО Документ.Ссылка = ВТ_ДокументыСУсловием.Ссылка
ГДЕ
    Документ.Дата >= &ДатаНачала

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

Работа с составными типами данных в условиях

Часто реквизиты в 1С имеют составной тип (например, поле Владелец или Субконто). Сравнение таких полей в запросах требует особой осторожности. Проанализируем ситуацию: если мы просто сравним ТЧ.Реквизит = &Значение, и &Значение имеет другой тип, отличный от типа данных в строке, запрос может работать медленно или вернуть неожиданный результат.

Для корректной работы с составными типами используем функцию ТИПЗНАЧЕНИЯ или ВЫРАЗИТЬ. Выясним причину, почему это важно: когда мы используем ВЫРАЗИТЬ, СУБД заранее знает, к какой физической таблице обращаться, что существенно оптимизирует план запроса.

Пример проверки типа в запросе:


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

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

Особенности обработки NULL при левом соединении

При использовании ЛЕВОЕ СОЕДИНЕНИЕ крайне важно помнить о значениях NULL. Если в правой таблице (табличной части) не найдено строк, соответствующих условию связи, все поля этой таблицы в результате запроса примут значение NULL.

Посмотрим на пример функции ЕСТЬNULL, которая помогает привести результат к понятному булеву значению:


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

В данном случае, если документ не попал во временную таблицу ВТ_РезультатыТЧ, функция ЕСТЬNULL заменит пустое значение на ЛОЖЬ, что и требуется по условию задачи.

Подведем итоги

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

Соблюдение этих рекомендаций позволит вам писать быстрые и отказоустойчивые запросы, которые будут корректно работать даже при изменении структуры данных или росте объема информационной базы.

← На главную