Почему в СКД возникает ошибка «Таблица не найдена» для временной таблицы и как это исправить

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

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

Проблема: Консоль запросов против СКД

Рассмотрим типичную ситуацию. Программист создает запрос, состоящий из двух частей. В первой части он вычисляет количество рабочих дней по производственному календарю и помещает результат во временную таблицу. Во второй части он соединяет эту таблицу с основными данными (например, этапами сменных заданий), чтобы рассчитать план. В консоли запросов такой код выполняется без нареканий.

Пример исходного запроса:


ВЫБРАТЬ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ РегламентированныйПроизводственныйКалендарь.ДатаКалендаря) КАК КоличествоРабочихДней,
    РегламентированныйПроизводственныйКалендарь.ВидДня КАК ВидДня
ПОМЕСТИТЬ ВТ_РабочихДней
ИЗ
    РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
ГДЕ
    РегламентированныйПроизводственныйКалендарь.ДатаКалендаря МЕЖДУ &НачалоПериода И &КонецПериода
    И РегламентированныйПроизводственныйКалендарь.ВидДня = &Рабочий
СГРУППИРОВАТЬ ПО
    РегламентированныйПроизводственныйКалендарь.ВидДня
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    индСменноеЗаданиеЭтапы.Станок,
    СУММА(индСменноеЗаданиеЭтапы.ВремяВыполненияФакт) КАК Факт,
    21 * РабочихДней.КоличествоРабочихДней КАК План
ИЗ
    Документ.индСменноеЗадание.Этапы КАК индСменноеЗаданиеЭтапы
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_РабочихДней КАК РабочихДней
        ПО (ИСТИНА)
ГДЕ
    индСменноеЗаданиеЭтапы.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
    индСменноеЗаданиеЭтапы.Станок,
    21 * РабочихДней.КоличествоРабочихДней

Однако при запуске этого же запроса в составе набора данных СКД пользователь получает ошибку: {(7, 25)}: Таблица не найдена "РабочихДней". Давайте разберемся, почему это происходит.

Причина: Интеллектуальная оптимизация СКД

Выясним причину такого поведения системы. В отличие от обычной консоли запросов, которая отправляет текст в СУБД «как есть», СКД является генератором запросов. Она анализирует настройки компоновки (выбранные поля, отборы, группировки) и на их основе перестраивает исходный текст запроса.

Основной механизм здесь — оптимизация. Если СКД «считает», что какое-то поле или таблица не используются в текущем варианте отчета (не выведены в список полей, не участвуют в группировках), она просто удаляет их из финального SQL-запроса для экономии ресурсов. В нашем примере проблема кроется в соединении ПО (ИСТИНА). Для оптимизатора СКД такое соединение выглядит как потенциально избыточное. Если поле План не выбрано явно в настройках отчета как ресурс или поле группировки, система принимает решение: «Данные из временной таблицы ВТ_РабочихДней не нужны, значит, удаляем ее создание».

Но происходит критическая ошибка алгоритма: СКД удаляет блок ПОМЕСТИТЬ ВТ_РабочихДней, но при этом в основном запросе оставляет ВНУТРЕННЕЕ СОЕДИНЕНИЕ или упоминание полей этой таблицы. В итоге СУБД получает запрос, который ссылается на несуществующую таблицу.

Решение 1: Использование полей в настройках отчета

Самый простой и быстрый способ проверить, в оптимизации ли дело — это принудительно использовать поле из «пропавшей» таблицы в настройках. Проанализируем, как это сделать:

  1. Откройте настройки отчета в конфигураторе или в пользовательском режиме.
  2. Добавьте поле, вычисляемое на основе временной таблицы (в нашем случае это План), в список выбранных полей или в группировку.
  3. Если поле должно суммироваться, добавьте его на вкладку «Ресурсы».

Как только поле становится «нужным» для вывода результата, СКД перестает удалять временную таблицу из запроса, и ошибка исчезает. Это подтверждается опытом: постановка поля План в ресурсы мгновенно «оживляет» отчет.

Решение 2: Флаг «Обязательное» в наборе данных

Рассмотрим более профессиональный способ решения, который не зависит от того, какие поля пользователь выберет в настройках. Мы можем жестко указать системе компоновки, что определенные поля всегда должны присутствовать в запросе.

Разберем по шагам, как настроить обязательность полей:

  1. Перейдите в конструктор схемы компоновки данных на закладку «Наборы данных».
  2. В таблице полей найдите поля, которые приходят из вашей временной таблицы (например, КоличествоРабочихДней).
  3. В колонке «Обязательное» (Mandatory) установите флажок.

Установка этого флага сообщает оптимизатору: «Независимо от того, выбрал ли пользователь это поле в настройках, ты обязан включить его (и таблицу, из которой оно берется) в итоговый запрос». Это наиболее стабильный вариант, гарантирующий работу отчета при любых пользовательских настройках.

Решение 3: Отключение оптимизации запроса

Если запрос слишком сложный и СКД продолжает вести себя непредсказуемо, мы можем полностью или частично ограничить ее «самодеятельность». Посмотрим на доступные инструменты:

Отключение автозаполнения: Если снять флаг «Автозаполнение» у набора данных, СКД перестанет автоматически подтягивать поля и пытаться оптимизировать связи. Вам придется вручную описать все доступные поля и параметры, но это даст полный контроль над структурой запроса.

Свойство «Использовать оптимизацию запроса»: В свойствах самого отчета (корневой элемент в дереве СКД) существует признак ИспользоватьОптимизациюЗапроса. Если установить его в значение Ложь, СКД будет передавать запрос практически в первозданном виде. Однако помните, что это может замедлить работу отчета на очень больших объемах данных, так как в SQL будут уходить даже те соединения, которые в данный момент не нужны пользователю.

Рекомендации по написанию запросов для СКД

Чтобы избежать подобных проблем в будущем, разберем несколько правил хорошего тона при проектировании запросов в СКД:

  1. Избегайте соединений по «ИСТИНА»: Старайтесь, чтобы таблицы имели логическую связь через поля. Если вам нужно соединить данные с константой или итогом из одной строки, попробуйте передавать это значение через Параметры или используйте связи наборов данных на соответствующей вкладке СКД.
  2. Проверяйте временные таблицы: Если вы используете временные таблицы, всегда следите за тем, чтобы хотя бы одно поле из финальной выборки, связанной с этой таблицей, было отмечено как Роль: Обязательное или использовалось в ресурсах.
  3. Функция ЕСТЬNULL: При обращении к полям временных таблиц в левых или полных соединениях всегда используйте ЕСТЬNULL(Таблица.Поле, 0). Это помогает СКД лучше понимать зависимости типов данных.

Подведем итог. Ошибка «Таблица не найдена» в СКД — это не ошибка вашего SQL-кода, а следствие работы внутреннего «улучшайзера» 1С. Понимая механизмы оптимизации и используя флаг «Обязательное», вы сможете создавать стабильные и быстрые отчеты, которые не ломаются при изменении состава колонок пользователем.

← На главную