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