При построении отчетов для сверки данных (например, при сравнении планового графика платежей по договору и фактических документов оплат) разработчики часто используют ПОЛНОЕ СОЕДИНЕНИЕ. Однако на практике возникает типичная ситуация: запрос возвращает только те строки, для которых нашлись совпадения в обеих таблицах, а строки без пар отсекаются. Разберем по шагам, почему так происходит и как правильно составить запрос для получения всех данных.
Проанализируем механику работы языка запросов 1С. Когда выполняется ПОЛНОЕ СОЕДИНЕНИЕ, платформа выбирает совпавшие записи из обеих таблиц, а для несовпавших строк подставляет значение NULL в поля отсутствующей стороны.
Классическая ошибка заключается в добавлении фильтрации по полям соединяемых таблиц в секцию ГДЕ. Если в секции ГДЕ указано условие вида:
ГДЕ
ДоговорыКонтрагентовА_Оплаты.А_СуммаСНДС = СписаниеСРасчетногоСчета.СуммаДокумента
или любой другой фильтр по полю правой или левой таблицы, то при проверке строки, где одно из полей равно NULL, результат логического выражения становится равен Ложь (так как любое сравнение с NULL дает неопределенный результат). В итоге все несовпавшие строки отбрасываются, и ПОЛНОЕ СОЕДИНЕНИЕ фактически превращается во ВНУТРЕННЕЕ СОЕДИНЕНИЕ.
Чтобы сохранить несовпавшие записи с полями со значением NULL, все условия связывания таблиц необходимо выносить непосредственно в секцию ПО конструкции соединения.
Рассмотрим пример правильного написания запроса:
ВЫБРАТЬ
ДоговорыКонтрагентовА_Оплаты.Ссылка КАК Договор,
ДоговорыКонтрагентовА_Оплаты.А_Дата КАК ДатаПлан,
ДоговорыКонтрагентовА_Оплаты.А_СуммаСНДС КАК СуммаПлан,
СписаниеСРасчетногоСчета.Ссылка КАК ДокументОплаты,
СписаниеСРасчетногоСчета.СуммаДокумента КАК СуммаФакт
ИЗ
Справочник.ДоговорыКонтрагентов.А_Оплаты КАК ДоговорыКонтрагентовА_Оплаты
ПОЛНОЕ СОЕДИНЕНИЕ Документ.СписаниеСРасчетногоСчета КАК СписаниеСРасчетногоСчета
ПО ДоговорыКонтрагентовА_Оплаты.Ссылка = СписаниеСРасчетногоСчета.ДоговорКонтрагента
И ДоговорыКонтрагентовА_Оплаты.А_СуммаСНДС = СписаниеСРасчетногоСчета.СуммаДокумента
При таком оформлении строки, у которых совпадают и договор, и сумма, будут выведены в одной строке. Записи с несовпавшими суммами или договорами также войдут в итоговую выборку, а в отсутствующих полях будет находиться NULL.
Если задача состоит в том, чтобы связать документы и плановые данные по договору, а разницу или совпадение сумм наглядно отобразить в отчете, рекомендуется выполнять соединение только по ключу договора, используя условное выражение ВЫБОР КОГДА для индикации расхождений.
Посмотрим на пример такого запроса:
ВЫБРАТЬ
ДоговорыКонтрагентовА_Оплаты.Ссылка КАК Договор,
ДоговорыКонтрагентовА_Оплаты.А_Дата КАК ДатаПлан,
ДоговорыКонтрагентовА_Оплаты.А_СуммаСНДС КАК СуммаПлан,
СписаниеСРасчетногоСчета.ДоговорКонтрагента КАК ДоговорФакт,
СписаниеСРасчетногоСчета.СуммаДокумента КАК СуммаФакт,
ВЫБОР
КОГДА ДоговорыКонтрагентовА_Оплаты.А_СуммаСНДС = СписаниеСРасчетногоСчета.СуммаДокумента
ТОГДА 0
ИНАЧЕ 1
КОНЕЦ КАК СуммаРасходится
ИЗ
Справочник.ДоговорыКонтрагентов.А_Оплаты КАК ДоговорыКонтрагентовА_Оплаты
ПОЛНОЕ СОЕДИНЕНИЕ Документ.СписаниеСРасчетногоСчета КАК СписаниеСРасчетногоСчета
ПО (ДоговорыКонтрагентовА_Оплаты.Ссылка = СписаниеСРасчетногоСчета.ДоговорКонтрагента)
УПОРЯДОЧИТЬ ПО
СуммаРасходится
Поле СуммаРасходится позволит сгруппировать или отсортировать данные, быстро выделив совпадающие платежи и позиции с расхождениями.
При прямом полном соединении табличной части справочника и реальной таблицы документов возможна проблема задвоения данных (декартово произведение строк, если по одному договору есть несколько одинаковых сумм), а также снижение производительности на больших объемах данных.
Разберем более надежный и эффективный подход с использованием временных таблиц и объединения выборки:
РасшифровкаПлатежа).
ОБЪЕДИНИТЬ ВСЕ с последующей группировкой по договору для точного подсчета итогов и дельты.
Рассмотрим пример консолидирующего запроса:
ВЫБРАТЬ
Договоры.Ссылка КАК Договор,
Договоры.А_СуммаСНДС КАК СуммаПлан,
0 КАК СуммаФакт
ПОМЕСТИТЬ ВТ_Данные
ИЗ
Справочник.ДоговорыКонтрагентов.А_Оплаты КАК Договоры
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Списание.ДоговорКонтрагента КАК Договор,
0 КАК СуммаПлан,
Списание.СуммаДокумента КАК СуммаФакт
ИЗ
Документ.СписаниеСРасчетногоСчета КАК Списание
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ.Договор КАК Договор,
СУММА(ВТ.СуммаПлан) КАК СуммаПлан,
СУММА(ВТ.СуммаФакт) КАК СуммаФакт,
СУММА(ВТ.СуммаПлан - ВТ.СуммаФакт) КАК Отклонение
ИЗ
ВТ_Данные КАК ВТ
СГРУППИРОВАТЬ ПО
ВТ.Договор
При проведении сверки плановых и фактических оплат рекомендуем соблюдать следующие правила платформы 1С:
СуммаПлан - СуммаФакт) в соединениях всегда используйте функцию ЕСТЬNULL(Поле, 0). В противном случае любые операции с NULL приведут к пустому результату.
РасшифровкаПлатежа.