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

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

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

Суть проблемы: Механизм оптимизации запроса в СКД

Система компоновки данных — это не просто инструмент для выполнения SQL-запроса. Это интеллектуальный конструктор, который перестраивает ваш исходный текст запроса под конкретные настройки пользователя. Когда вы формируете отчет, компоновщик анализирует, какие поля выбраны в "Выбранных полях", какие участвуют в "Группировках", а какие — в "Отборах".

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

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

Рассмотрим подробнее исходный запрос, который вызывает такое поведение:


ВЫБРАТЬ
    НормыВыдачиСрезПоследних.Профессия КАК Профессия,
    НормыВыдачиСрезПоследних.ОбъединениеНорм КАК ОбъединениеНорм,
    1 КАК Количество
ПОМЕСТИТЬ Исходная
ИЗ
    РегистрСведений.НормыВыдачи.СрезПоследних КАК НормыВыдачиСрезПоследних
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Исходная.Профессия КАК Профессия,
    Исходная.ОбъединениеНорм КАК ОбъединениеНорм,
    Исходная.Количество КАК КоличествоРазныхТоваров
ИЗ
    Исходная КАК Исходная

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

Самый быстрый и эффективный способ запретить СКД оптимизировать запрос — это использование ролей полей. Посмотрим на алгоритм действий:

  1. Перейдите на закладку "Набор данных" в схеме компоновки.
  2. Найдите поле, которое "исчезает" и вызывает схлопывание строк (в нашем примере это ОбъединениеНорм).
  3. Нажмите на кнопку в колонке "Роль".
  4. В открывшемся окне установите флажок "Обязательное".

Что это дает: Установка этого флага сообщает компоновщику, что данное поле должно присутствовать в запросе ВСЕГДА, даже если пользователь не выбрал его в настройках отчета. Таким образом, группировка в SQL-запросе будет всегда содержать это поле, и количество строк не уменьшится. Однако помните, что это может повысить нагрузку на базу данных при очень больших объемах информации.

Решение №2: Правильная настройка ресурсов

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

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

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

Количество(Различные ОбъединениеНорм)

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

Решение №3: Отключение автозаполнения

Если вы хотите полностью контролировать текст запроса, можно отключить механизм "Автозаполнение" (флажок на закладке "Набор данных").

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

Пример настройки секции ВЫБРАТЬ с использованием расширения языка запросов:


ВЫБРАТЬ
    Исходная.Профессия КАК Профессия,
    {Исходная.ОбъединениеНорм КАК ОбъединениеНорм,}
    Исходная.Количество КАК Количество
ИЗ
    Исходная КАК Исходная

Разница между агрегатными функциями в запросе и в СКД

Важно понимать разницу между СУММА(), КОЛИЧЕСТВО() и КОЛИЧЕСТВО(РАЗЛИЧНЫЕ). Рассмотрим на примере данных:

Если у нас есть записи: 1, 1, 1, 2, 2

В обсуждаемой теме автор использовал КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Исходная.Количество), где Количество всегда равно 1. Естественно, количество различных значений единицы всегда равно 1, что и приводило к неверному результату. Если ваша цель — считать количество товаров, агрегатную функцию нужно применять к полю Товар, а не к техническому полю с единицей.

Рекомендации для стабильной работы отчетов

Чтобы избежать подобных ситуаций в будущем, рекомендуем придерживаться следующих правил:

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

← На главную