Как правильно фильтровать подчиненные документы по дате при левом соединении в запросе 1С СКД

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

Разберем распространенную задачу при разработке отчетов на базе системы компоновки данных (СКД) или обычных запросов в 1С. Очень часто требуется вывести полный список родительских документов (например, заказов или счетов) и привязать к ним подчиненные документы (оплаты, приходы на счет, расходы из кассы). При этом нужно наложить фильтр по дате на подчиненный документ так, чтобы сами родительские документы не исчезали из итоговой выборки, даже если по ним не было оплат в указанном периоде.

Анализ причины проблемы: почему «ЛЕВОЕ СОЕДИНЕНИЕ» начинает работать как «ВНУТРЕННЕЕ»

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

Посмотрим на пример запроса, содержащего ошибку в логике отбора:


ВЫБРАТЬ
    СчетНаОплату1.Ссылка КАК СчетНаОплату,
    РП.Ссылка.Ссылка КАК ПоступлениеНаСчет,
    РП.СчетНаОплату.Ссылка КАК СчетНаОплатуСсылка
ИЗ
    Документ.СчетНаОплату КАК СчетНаОплату1
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеНаСчет.РасшифровкаПлатежа КАК РП
        ПО РП.СчетНаОплату.Ссылка = СчетНаОплату1.Ссылка
ГДЕ
    РП.Ссылка.Дата МЕЖДУ &ДатаПриходовФактНачало И &ДатаПриходовФактКонец

Выясним причину, почему такой запрос работает некорректно. Когда мы помещаем условие отбора по дате подчиненного документа РП.Ссылка.Дата в секцию ГДЕ, СУБД применяет фильтр к уже сформированной таблице соединения. Если у счета нет подчиненных платежей или их дата не попадает в интервал, поля таблицы РП принимают значение NULL. Но проверка NULL МЕЖДУ &Дата... И &Дата... дает ложь, и СУБД отсекает всю строку целиком, включая сам родительский счет.

Таким образом, использование секции ГДЕ с полем правой (присоединенной) таблицы фактически превращает ЛЕВОЕ СОЕДИНЕНИЕ во ВНУТРЕННЕЕ СОЕДИНЕНИЕ (INNER JOIN).

Решение: перенос условия отбора в секцию «ПО» условия соединения

Чтобы сохранить принцип левого соединения (выводить все счета, а подчиненные платежи выводить только в том случае, если они соответствуют периоду), необходимо перенести условие фильтрации из секции ГДЕ непосредственно в секцию соединения ПО.

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


ВЫБРАТЬ
    СчетНаОплату1.Ссылка КАК СчетНаОплату,
    РП.Ссылка.Ссылка КАК ПоступлениеНаСчет,
    РП.СчетНаОплату.Ссылка КАК СчетНаОплатуСсылка
ИЗ
    Документ.СчетНаОплату КАК СчетНаОплату1
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеНаСчет.РасшифровкаПлатежа КАК РП
        ПО (РП.СчетНаОплату.Ссылка = СчетНаОплату1.Ссылка)
            И (РП.Ссылка.Дата МЕЖДУ &ДатаПриходовФактНачало И &ДатаПриходовФактКонец)

Разберем по шагам, как работает этот запрос:

  1. СУБД перебирает все записи таблицы Документ.СчетНаОплату.
  2. Для каждого счета ищется подчиненная запись из РасшифровкаПлатежа, которая удовлетворяет одновременно двум условиям: совпадение ссылки на счет и попадание даты документа оплаты в заданный период.
  3. Если подчиненный документ найден, он присоединяется к строке. Если не найден — строка счета всё равно выводится, а поля оплат заполняются значениями NULL.

Решение с использованием возможностей СКД

Если отчет разрабатывается в Системе компоновки данных, мы можем использовать дополнительные механизмы платформы 1С для управления гибкими отборами:

  1. Разделение на несколько наборов данных: Мы можем вынести Заказы/Счета в НаборДанных1, а платежи — в НаборДанных2. На вкладке «Связи наборов данных» настраиваем связь по ссылке. В этом случае, если пользователь установит отбор по дате в настройках СКД на поле второго набора данных, СКД автоматически применит внутреннюю связь и отфильтрует заказы. Если отбор отключен — связи останутся левыми.
  2. Расширение языка запросов СКД: Внутри текста запроса можно использовать специальные фигурные скобки компоновки данных:
    
    {ГДЕ
        РП.Ссылка.Дата МЕЖДУ &ДатаПриходовФактНачало И &ДатаПриходовФактКонец}
    
    В этом случае СКД сама добавит условие в текст запроса только при условии, что соответствующий параметр или отбор включен пользователем в настройках отчета.
← На главную