Почему запрос работает в консоли запросов, но возвращает пустой результат в СКД?

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

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

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

Причина 1. Оптимизация и трансформация запроса генератором СКД

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

Если в наборе данных включен признак Автозаполнение, система автоматически:

  1. Переносит пользовательские отборы из настроек отчета в условия виртуальных таблиц и блок ГДЕ.
  2. Удаляет из выборки поля и таблицы, которые не задействованы в текущей структуре отчета.
  3. Пытается связать стандартные параметры периода (НачалоПериода и КонецПериода) с параметрами виртуальных таблиц.

Если в тексте запроса разработчик убирает параметры из заголовка виртуальной таблицы и пытается вручную прописать условие вида ГДЕ Регистратор.Дата МЕЖДУ &НачалоПериода И &КонецПериода, возникает логический конфликт с механизмами автозаполнения СКД, что приводит к некорректной генерации результирующего SQL-запроса и пустой выборке.

Причина 2. Ошибочное разыменование через Регистратор.Дата вместо поля Период

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

  1. Падение производительности: СУБД вынуждена соединять основную таблицу регистра с десятками таблиц документов.
  2. Проблемы с фильтрацией: если в выборку попадают записи с незаполненным или специфическим регистратором (например, документ удален или очищен), условие отбора отсекает нужные строки.
  3. Игнорирование индексов: в таблицах движений и оборотов с периодичностью по регистратору дата записи уже хранится в индексированном поле Период. Фильтрация по полю Регистратор.Дата не использует индекс по периоду таблицы регистра.

Решение 1. Использование расширения языка СКД (фигурные скобки)

Для того чтобы параметры виртуальной таблицы применялись гибко и динамически (только тогда, когда они заданы в отчете), необходимо использовать синтаксис расширения языка запросов СКД — фигурные скобки {}.

Посмотрим на пример правильного описания виртуальной таблицы оборотов:


ВЫБРАТЬ
    ПродажиОбороты.Номенклатура КАК Номенклатура,
    ПродажиОбороты.КоличествоОборот КАК КоличествоОборот,
    ПродажиОбороты.СуммаОборот КАК СуммаОборот
ИЗ
    РегистрНакопления.Продажи.Обороты({(&НачалоПериода)}, {(&КонецПериода)}, Регистратор, {УсловиеПолей}) КАК ПродажиОбороты

Рассмотрим, как это работает:

  1. Конструкция {(&НачалоПериода)} и {(&КонецПериода)} сообщает СКД, что если соответствующие параметры заданы и включены в настройках отчета, они будут переданы в параметры виртуальной таблицы.
  2. Если пользователь не указал дату начала или окончания, СКД исключит этот параметр из итогового запроса к СУБД, не ограничивая интервал выборки с соответствующей стороны.
  3. Указание периодичности Регистратор позволяет получать детальные данные с точностью до документа-регистратора, сохраняя корректную работу итогов.

Решение 2. Корректное использование стандартных параметров виртуальной таблицы

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


ВЫБРАТЬ
    ТоварыНаСкладахОбороты.Склад КАК Склад,
    ТоварыНаСкладахОбороты.Номенклатура КАК Номенклатура,
    ТоварыНаСкладахОбороты.Регистратор КАК Регистратор,
    ТоварыНаСкладахОбороты.Период КАК Период,
    ТоварыНаСкладахОбороты.КоличествоОборот КАК КоличествоОборот
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Обороты(&НачалоПериода, &КонецПериода, Регистратор, ) КАК ТоварыНаСкладахОбороты

Проанализируем ключевые настройки для этого варианта на вкладке Параметры в СКД:

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

Решение 3. Отключение автозаполнения для полного контроля над запросом

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

  1. В конструкторе схемы компоновки данных на вкладке Наборы данных снимем флаг Автозаполнение у набора данных.
  2. В тексте запроса вручную опишем доступные поля для выбора и отбора с помощью инструкций расширения языка: {ВЫБРАТЬ ...}, {ГДЕ ...}.
  3. В таком режиме СКД выполнит запрос строго в соответствии с описанной схемой, исключая автоматические неявные трансформации условий.
← На главную