Почему результаты запроса в консоли и в отчете СКД различаются: разбираем причины и решения

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет Промышленность, строительство и АПК
← На главную

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

Анализ проблемы: отличия Консоли от СКД

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

  1. Оптимизатор запросов (Query Generator): Если в настройках отчета (в колонках) не выбраны поля из какой-то таблицы, участвующей в ЛЕВОМ СОЕДИНЕНИИ, СКД может просто выкинуть эту таблицу из итогового запроса. Если на эту таблицу было наложено условие в секции ГДЕ, логика отчета нарушится.
  2. Кэширование внешних отчетов: Если отчет зарегистрирован в справочнике «Дополнительные отчеты и обработки», платформа кэширует его схему. Даже при открытии файла с диска через «Файл — Открыть», система может подтянуть старые настройки из кэша.
  3. Пользовательские настройки: СКД сохраняет настройки (отборы, группировки) для каждого пользователя. Если вы изменили запрос в конфигураторе, но у пользователя остались старые настройки, они могут перекрывать логику нового запроса.

Разбор практического примера запроса

Рассмотрим ситуацию, описанную в теме. В запросе используются временные таблицы для сбора данных по заказам, производству и выпуску продукции. Посмотрим на фрагмент итогового объединения:


ВЫБРАТЬ
    Перемещение.Номенклатура КАК Номенклатура,
    Перемещение.Характеристика КАК Характеристика,
    СУММА(Перемещение.КоличествоУпаковок - ЕСТЬNULL(Производство.КоличествоУпаковок, 0)) КАК ОсталосьЗаказать,
    ЕСТЬNULL(Выпуск.КоличествоУпаковок, 0) КАК Выпущено,
    Перемещение.Ссылка КАК Ссылка,
    СостоянияВнутреннихЗаказов.Заказ КАК Заказ
ИЗ
    РегистрСведений.СостоянияВнутреннихЗаказов КАК СостоянияВнутреннихЗаказов
ЛЕВОЕ СОЕДИНЕНИЕ Перемещение КАК Перемещение
ПО СостоянияВнутреннихЗаказов.Заказ = Перемещение.Ссылка
ГДЕ
    СостоянияВнутреннихЗаказов.Состояние = ЗНАЧЕНИЕ(Перечисление.СостоянияВнутреннихЗаказов.ГотовКОбеспечению)

В данном случае условие ГДЕ наложено на основную таблицу СостоянияВнутреннихЗаказов. Если компоновщик СКД решит, что поле Состояние не является обязательным для вывода, он может некорректно применить фильтрацию в итоговом SQL-запросе.

Решение №1: Перенос условий в секцию ПО

Одной из рекомендаций при работе с СКД является перенос условий фильтрации из секции ГДЕ непосредственно в условия соединения ПО. Это гарантирует, что фильтрация будет применена на уровне соединения таблиц, что более предсказуемо для компоновщика макета. Попробуем изменить структуру соединения:


ИЗ
    РегистрСведений.СостоянияВнутреннихЗаказов КАК СостоянияВнутреннихЗаказов
ЛЕВОЕ СОЕДИНЕНИЕ Перемещение КАК Перемещение
ПО СостоянияВнутреннихЗаказов.Заказ = Перемещение.Ссылка
   И СостоянияВнутреннихЗаказов.Состояние = ЗНАЧЕНИЕ(Перечисление.СостоянияВнутреннихЗаказов.ГотовКОбеспечению)

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

Решение №2: Управление обязательными полями

Если вы хотите, чтобы определенные поля или таблицы всегда участвовали в запросе, независимо от того, выбрал ли их пользователь в настройках отчета, выполним следующие шаги в конструкторе СКД:

  1. Откроем вкладку «Наборы данных».
  2. Для полей Состояние и Заказ установим флаг «Обязательное».
  3. Если используется «Автозаполнение», убедимся, что компоновщик правильно определил роли полей.

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

Решение №3: Борьба с кэшированием и «зависшими» настройками

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

Использование расширений языка запросов СКД

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


ГДЕ
    СостоянияВнутреннихЗаказов.Состояние = ЗНАЧЕНИЕ(Перечисление.СостоянияВнутреннихЗаказов.ГотовКОбеспечению)
    И СостоянияВнутреннихЗаказов.Заказ {(&ЗаказОтбор)}

Такой подход делает запрос более гибким и понятным для механизмов компоновки. Выясним причину, почему создание нового отчета помогло автору темы: при создании нового объекта 1С генерирует новый уникальный идентификатор (UID). Все старые настройки, кэши и ошибки интерпретации метаданных, привязанные к старому ID, перестают влиять на выполнение кода.

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

← На главную