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