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