Почему не выводятся данные в отчет СКД при установке отбора по периоду?

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

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

Причины формирования пустого отчета при отборе по периоду

Выясним основные причины, из-за которых отбор по датам отсекает все записи:

  1. Неверная обработка времени конца периода. Если параметры схемы НачалоПериода и КонецПериода имеют состав даты «Только дата», время автоматически приводится к 00:00:00. В этом случае жесткое условие Период <= &КонецПериода исключает все движения, совершенные в течение конечного дня интервала, кроме документов, записанных строго в полночь.
  2. Отключенные или пустые параметры в настройках. Если параметры периода прописаны в основном тексте запроса жестко (без фигурных скобок {}), СКД обязана передать их значения в СУБД. Если в пользовательских настройках флажок использования параметра снят или значение не выбрано, платформа подставляет пустую дату (0001-01-01 00:00:00). В результате условие не выполняется ни для одной строки.
  3. Кэширование настроек формы. В режиме предприятия платформа сохраняет индивидуальные настройки пользователя. Если разработчик скорректировал значения по умолчанию в конфигураторе, у пользователя отчет может открываться со старыми сохраненными значениями, где даты не заполнены.
  4. Ошибки прямого чтения физической таблицы. Разработчики нередко обращаются к реальной физической таблице РегистрНакопления.Продажи напрямую только ради получения документа-регистратора, полагая, что в виртуальных таблицах оборотов этого поля нет. При прямом чтении СУБД сканирует всю таблицу, а не оптимизированные итоги, что ухудшает производительность и повышает риск блокировок.

Решение 1: Переход на виртуальную таблицу с периодичностью по регистратору

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

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


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

Обратим внимание на третий параметр виртуальной таблицы: значение Регистратор указывает платформе разворачивать обороты с детализацией до документа движения. Это позволяет получить точные данные без обращения к таблице движений регистра напрямую.

Решение 2: Корректная настройка параметров периода через СтандартныйПериод

Чтобы избежать отсечения документов из-за времени 00:00:00 и исключить пустые даты, свяжем границы с параметром типа СтандартныйПериод. Разберем настройку по шагам:

  1. Перейдем на вкладку Параметры схемы компоновки данных.
  2. Создадим новый параметр, например ПериодОтчета, и назначим ему тип СтандартныйПериод. Сделаем его доступным для пользователя в настройках.
  3. Для параметров НачалоПериода и КонецПериода установим флажок Ограничение доступности, чтобы скрыть их из диалога настроек.
  4. В колонке Выражение для параметра НачалоПериода укажем:
    &ПериодОтчета.ДатаНачала
  5. В колонке Выражение для параметра КонецПериода пропишем формулу:
    КонецПериода(&ПериодОтчета.ДатаОкончания, "День")

Данная конструкция гарантирует, что конец периода всегда будет указывать на последнюю секунду дня (23:59:59), а параметры всегда будут заполнены согласованно.

Решение 3: Оптимизация отборов в виртуальной таблице

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

Рассмотрим пример запроса с оптимальной фильтрацией:


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

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

Способ диагностики: как увидеть реальный запрос СКД

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


КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.ПолучитьНастройки());

// Выводим фактический текст запроса первого набора данных
ТекстФактическогоЗапроса = МакетКомпоновки.НаборыДанных[0].Запрос;

// Проверяем реальные значения переданных параметров
Для Каждого Параметр Из МакетКомпоновки.ЗначенияПараметров Цикл
    Сообщить(Параметр.Имя + " = " + Строка(Параметр.Значение));
КонецЦикла;

Проанализировав полученный текст и параметры, можно сразу увидеть, какое условие исключает строки и какое значение передается в границы дат.

← На главную