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