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