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