Почему ПОЛНОЕ СОЕДИНЕНИЕ в запросе 1С работает некорректно и как это исправить?

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

При разработке отчетов в 1С:Предприятие 8 часто возникает необходимость вывести данные из нескольких табличных частей одного документа. Казалось бы, ПОЛНОЕ СОЕДИНЕНИЕ — идеальный инструмент для объединения этих данных. Однако на практике разработчики часто сталкиваются с ситуацией, когда данные, существующие в одной табличной части, «исчезают» из выборки, если в другой табличной части соответствующих записей нет. Давайте разберем, почему это происходит и как правильно организовать получение данных.

Причина проблемы: как работает ГДЕ и ПОЛНОЕ СОЕДИНЕНИЕ

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

Как только мы добавляем условие в секцию ГДЕ, например Ссылка.Проведен, мы принудительно отсекаем строки, которые не удовлетворяют этому условию. Поскольку NULL не является «истиной», любая проверка с его участием в блоке ГДЕ приводит к тому, что запись просто исключается из итогового результата. В итоге ПОЛНОЕ СОЕДИНЕНИЕ фактически превращается во ВНУТРЕННЕЕ СОЕДИНЕНИЕ, так как все записи, где хотя бы одна таблица пуста, отсеиваются.

Способ решения №1: использование функции ЕСТЬNULL в условиях

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

Рассмотрим пример правильного написания условий:


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

Способ решения №2: использование временных таблиц (рекомендуемый подход)

Более надежный и читаемый способ — это разделение задачи на этапы. Мы можем поместить данные из каждой табличной части во временные таблицы (ВТ), предварительно отфильтровав их, а затем соединить эти таблицы между собой. Это делает запрос логически понятным и позволяет избежать путаницы с NULL.

Разберем этапы создания такого запроса:

  1. Выбираем данные из каждой ТЧ отдельно в разные временные таблицы, применяя все необходимые фильтры (период, проведение) на этом этапе.
  2. Группируем данные внутри временных таблиц (например, суммируем Количество или Расстояние).
  3. Соединяем полученные таблицы в финальном запросе, используя ЛЕВОЕ или ПОЛНОЕ соединение.

// Шаг 1: Получаем данные по топливу
ВЫБРАТЬ СУММА(Количество) КАК Количество, Ссылка 
ПОМЕСТИТЬ вт_Топливо 
ИЗ Документ.ПутевойЛист.Топливо 
ГДЕ Ссылка.Проведен И Ссылка.Дата МЕЖДУ &ДатаНач И &ДатаКон 
СГРУППИРОВАТЬ ПО Ссылка;

// Шаг 2: Получаем данные по маршрутам
ВЫБРАТЬ СУММА(Расстояние) КАК Расстояние, Ссылка 
ПОМЕСТИТЬ вт_Маршрут 
ИЗ Документ.ПутевойЛист.Маршрут 
ГДЕ Ссылка.Проведен И Ссылка.Дата МЕЖДУ &ДатаНач И &ДатаКон 
СГРУППИРОВАТЬ ПО Ссылка;

// Шаг 3: Объединяем результаты
ВЫБРАТЬ * 
ИЗ вт_Топливо КАК Т
ПОЛНОЕ СОЕДИНЕНИЕ вт_Маршрут КАК М ПО Т.Ссылка = М.Ссылка;

Почему важно правильно использовать оператор МЕЖДУ?

Многие разработчики сталкиваются с тем, что МЕЖДУ (или BETWEEN) «не работает». Важно понимать, что этот оператор — лишь сокращенная форма условий >= и <=. Если поле, по которому идет сравнение, содержит NULL, результат сравнения будет не определен, и строка не попадет в выборку. Поэтому при использовании временных таблиц мы фильтруем данные ДО их соединения, тем самым гарантируя, что NULL не попадет в условия фильтрации.

Итоговые рекомендации

Чтобы отчеты работали стабильно и быстро:

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

← На главную