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

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

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

Разберем причину: Механизм оптимизации запросов (Query Trimming)

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

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


ВЫБРАТЬ
    ПродажиОбороты.Покупатель,
    МИНИМУМ(ПродажиОбороты.Период) КАК ДатаПервогоЗаезда
ПОМЕСТИТЬ ТаблицаДатаПервогоЗаезда
ИЗ
    РегистрНакопления.Продажи.Обороты( , , Регистратор, ...) КАК ПродажиОбороты
СГРУППИРОВАТЬ ПО
    ПродажиОкупатель

Если в настройках отчета пользователь выводит только общую сумму продаж по подразделениям и не выводит поле Регистратор или ДатаПервогоЗаезда, СКД может решить, что детализация до регистратора во вложенном запросе избыточна. В результате она "схлопывает" группировки раньше времени или вовсе игнорирует расчеты, которые должны были произойти на уровне детальных записей. Итоги, которые должны были суммироваться на основе уникальных пар "Клиент-Регистратор", начинают считаться на основе уже агрегированных данных, что приводит к неверному результату.

Решение 1: Использование флага Обязательное

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

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

Важный момент: Флаг Обязательное сообщает компоновщику, что данное поле должно присутствовать в тексте SQL-запроса всегда, вне зависимости от настроек пользователя. Это гарантирует сохранение структуры группировок во временных таблицах.

Решение 2: Проблема периодичности в виртуальных таблицах

Часто в запросах к виртуальным таблицам (Обороты, ОстаткиИОбороты) в параметре Периодичность указывают значение Авто. Посмотрим на пример:


ИЗ
    РегистрНакопления.Продажи.Обороты(&ДатаНачала, &ДатаОкончания, Авто, ...) КАК ПродажиОбороты

При такой настройке состав полей периода в итоговом запросе будет динамически меняться. Если в отчете нет группировки по секундам или дням, СКД оптимизирует запрос так, что функция МИНИМУМ(Период) начнет возвращать начало месяца или года вместо точного времени документа. Это критично, если ваша бизнес-логика (например, определение "нового" клиента) завязана на конкретную дату или время заезда. Чтобы избежать этого, рекомендуется явно указывать минимально необходимую периодичность (например, Регистратор или Секунда) в параметрах виртуальной таблицы вместо значения Авто.

Решение 3: Правильный расчет ресурсов в СКД

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


ВЫБРАТЬ
    Продажи.Подразделение,
    СУММА(1) КАК КоличествоКлиентов,
    Продажи.Покупатель
ПОМЕСТИТЬ Итоговая
...
СГРУППИРОВАТЬ ПО
    Продажи.Подразделение,
    Продажи.Покупатель

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

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

Решение 4: Отказ от автозаполнения для сложных запросов

Если отчет строится на базе сложной цепочки временных таблиц, стандартный механизм Автозаполнение может некорректно определять роли полей. Выясним, как взять управление в свои руки:

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

Например, использование конструкции {ВЫБРАТЬ...} в тексте запроса позволяет жестко зафиксировать поля, которые не должны быть выброшены оптимизатором:


ВЫБРАТЬ
    Продажи.Подразделение КАК Подразделение,
    {Продажи.ДокументПродажи КАК ДокументПродажи}, -- поле доступно для выбора, но не мешает оптимизации
    Продажи.Покупатель КАК Покупатель
ИЗ
    Продажи КАК Продажи

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

← На главную