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

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

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

Механизм автоматической подмены параметров: выясняем причину

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

Проанализируем ситуацию: в исходном запросе автора используются две временные таблицы, каждая из которых берет данные из регистра ТоварыНаСкладах.Остатки. Однако на выходе вместо двух разных цифр (29 и 35) система выдает одинаковые значения (29 и 29). Это происходит потому, что на этапе компоновки макета СКД подставила одну и ту же дату в обе виртуальные таблицы, проигнорировав логику объединения ОБЪЕДИНИТЬ.

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

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

Посмотрим на пример правильного оформления параметров в тексте запроса:


ВЫБРАТЬ
    ТоварыНаСкладахОстатки.Склад,
    ТоварыНаСкладахОстатки.Номенклатура,
    ТоварыНаСкладахОстатки.КоличествоОстаток,
    &КонДата КАК ГруппировкаПериод
ПОМЕСТИТЬ втТекущиеОстатки
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки({&КонДата}, ) КАК ТоварыНаСкладахОстатки;

////////////////////////////////////////////////////////////////////////////////

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

Использование конструкции {&КонДата} сообщает системе компоновки: "Этот параметр управляется вручную, не пытайся заменить его на стандартный период". Это гарантирует, что в итоговом SQL-запросе к базе данных будут переданы именно те две разные даты, которые вы определили в настройках.

Решение 2: Настройка на вкладке "Компоновка данных"

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

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

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

Решение 3: Роли полей и итоговые записи

Иногда проблема кроется не только в параметрах дат, но и в том, как СКД рассчитывает итоги по группировкам. В тексте запроса автора присутствует конструкция ИТОГИ ПО ГруппировкаПериод. В СКД использовать предложение ИТОГИ внутри текста запроса не рекомендуется.

Система компоновки данных сама строит дерево итогов на основе ваших настроек группировок. Наличие ИТОГИ в тексте может привести к конфликту структур. Вместо этого выполним следующие действия:

Решение 4: Архитектурный подход через разные наборы данных

Если манипуляции с текстом запроса кажутся слишком громоздкими, проанализируем альтернативный вариант — использование нескольких Наборов данных - запрос.

Рассмотрим реализацию этого метода:

  1. Создаем НаборДанных1, где получаем остатки только на &КонДата.
  2. Создаем НаборДанных2, где получаем остатки только на &МесяцНазад.
  3. На вкладке Связи наборов данных связываем их по полям Номенклатура и Склад.

В этом случае параметры дат для каждой таблицы будут изолированы друг от друга, и СКД гарантированно не сможет их перепутать или объединить. Это "чистый" способ разделения логики, который упрощает отладку отчета.

Как проверить итоговый запрос (Отладка)

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

Пример анализа программным кодом:


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

Для Каждого ТекущийЗапрос Из МакетКомпоновки.Запросы Цикл
    Сообщить(ТекущийЗапрос.Текст);
КонецЦикла;

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

Подводя итог, помните: СКД — это мощный инструмент, который "думает" за разработчика. Чтобы получить предсказуемый результат в сложных отчетах с остатками, всегда явно ограничивайте область действия параметров виртуальных таблиц и доверяйте расчет итогов механизмам самой компоновки, а не тексту запроса.

← На главную