Почему полное соединение в запросе 1С работает как внутреннее и как правильно связать графики оплат с фактическими списаниями

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

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

Выясним причину: почему полное соединение превращается во внутреннее

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

Классическая ошибка заключается в добавлении фильтрации по полям соединяемых таблиц в секцию ГДЕ. Если в секции ГДЕ указано условие вида:


ГДЕ
    ДоговорыКонтрагентовА_Оплаты.А_СуммаСНДС = СписаниеСРасчетногоСчета.СуммаДокумента

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

Решение 1. Перенос условий в секцию связи ПО

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

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


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

При таком оформлении строки, у которых совпадают и договор, и сумма, будут выведены в одной строке. Записи с несовпавшими суммами или договорами также войдут в итоговую выборку, а в отсутствующих полях будет находиться NULL.

Решение 2. Соединение по договору с вычислением флага расхождений

Если задача состоит в том, чтобы связать документы и плановые данные по договору, а разницу или совпадение сумм наглядно отобразить в отчете, рекомендуется выполнять соединение только по ключу договора, используя условное выражение ВЫБОР КОГДА для индикации расхождений.

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


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

Поле СуммаРасходится позволит сгруппировать или отсортировать данные, быстро выделив совпадающие платежи и позиции с расхождениями.

Решение 3. Альтернативный подход через ОБЪЕДИНИТЬ ВСЕ и временные таблицы

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

Разберем более надежный и эффективный подход с использованием временных таблиц и объединения выборки:

  1. Формирование временной таблицы плановых данных: выбираем данные графика оплат, заменяя отсутствующий факт нулями.
  2. Формирование временной таблицы фактических оплат: выбираем суммы из документов (обращая внимание, что в типовых конфигурациях аналитика хранится в табличной части РасшифровкаПлатежа).
  3. Объединение и группировка: используем ОБЪЕДИНИТЬ ВСЕ с последующей группировкой по договору для точного подсчета итогов и дельты.

Рассмотрим пример консолидирующего запроса:


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

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Списание.ДоговорКонтрагента КАК Договор,
    0 КАК СуммаПлан,
    Списание.СуммаДокумента КАК СуммаФакт
ИЗ
    Документ.СписаниеСРасчетногоСчета КАК Списание
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ.Договор КАК Договор,
    СУММА(ВТ.СуммаПлан) КАК СуммаПлан,
    СУММА(ВТ.СуммаФакт) КАК СуммаФакт,
    СУММА(ВТ.СуммаПлан - ВТ.СуммаФакт) КАК Отклонение
ИЗ
    ВТ_Данные КАК ВТ
СГРУППИРОВАТЬ ПО
    ВТ.Договор

Важные правила при работе со сведением данных

При проведении сверки плановых и фактических оплат рекомендуем соблюдать следующие правила платформы 1С:

  1. Обработка NULL: При вычислении арифметических операций (например, разницы СуммаПлан - СуммаФакт) в соединениях всегда используйте функцию ЕСТЬNULL(Поле, 0). В противном случае любые операции с NULL приведут к пустому результату.
  2. Учет структуры документов: Убедитесь, где именно в документе списания хранится аналитика по договору. В большинства типовых решений (ERP, КА, УТ, БП) договор находится не в шапке, а в табличной части РасшифровкаПлатежа.
← На главную