Почему запрос из СКД выводит больше строк в обычном запросе 1С и как это исправить?

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

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

Почему возникают расхождения в количестве строк

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

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

Вариант 1. Адаптация текста запроса под обычный объект Запрос

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

Исходный запрос из СКД с необрабатываемыми фигурными скобками выглядел следующим образом:


&НаСервере
Процедура ЗаполнитьНаСервереБалансСчетовЗаДень()
    ОборотыДень       = Новый Запрос;
    ОборотыДень.Текст = "
        |ВЫБРАТЬ
        |    ХозрасчетныйОстаткиИОбороты.Организация           КАК Организация,
        |    ХозрасчетныйОстаткиИОбороты.Субконто1             КАК БанковскийСчет,
        |    ХозрасчетныйОстаткиИОбороты.СуммаНачальныйОстаток КАК НачальныйОстаток,
        |    ХозрасчетныйОстаткиИОбороты.СуммаОборотДт         КАК Поступление,
        |    ХозрасчетныйОстаткиИОбороты.СуммаОборотКт         КАК Списание,
        |    ХозрасчетныйОстаткиИОбороты.СуммаКонечныйОстаток  КАК КонечныйОстаток,
        |    ХозрасчетныйОстаткиИОбороты.ПериодСекунда         КАК ПериодСекунда
        |ИЗ
        |    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты({(НАЧАЛОПЕРИОДА(&Дата, ДЕНЬ)) КАК Поле2}, {(ДОБАВИТЬКДАТЕ(КОНЕЦПЕРИОДА(&Дата, ДЕНЬ), СЕКУНДА, 1)) КАК Поле2}, Авто, , Счет = ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.РасчетныеСчета), , ) КАК ХозрасчетныйОстаткиИОбороты";
    ОборотыДень.УстановитьПараметр("Дата", Дата);
    Рез = ОборотыДень.Выполнить();
    Если Не Рез.Пустой() Тогда
        БалансСчетовЗаДень.Загрузить(Рез.Выгрузить());
    КонецЕсли;
КонецПроцедуры

Чтобы привести данный запрос к корректному виду для обычного исполнения, выполним следующие шаги:

  1. Уберем фигурные скобки {} вокруг выражений периода.
  2. Уберем лишнее поле детализации ПериодСекунда, если итоговые данные нужны в свернутом виде по счетам и организациям.
  3. Передадим границы периода прямыми выражениями в параметры виртуальной таблицы.

Разберем итоговый рабочий вариант запроса:


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

Вариант 2. Программное выполнение схемы СКД с выводом в коллекцию значений

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

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


// 1. Получаем схему компоновки и настройки
СхемаСКД = ПолучитьМакет("СхемаКомпоновкиДанных");
НастройкиСКД = СхемаСКД.НастройкиПоУмолчанию;

// 2. Инициализируем компоновщик макета для коллекции значений
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(
    СхемаСКД, 
    НастройкиСКД, 
    , 
    , 
    Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений")
);

// 3. Выполняем компоновку данных
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);

// 4. Выводим результат в Таблицу Значений
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ТаблицаРезультата = Новый ТаблицаЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаРезультата);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

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

← На главную