При составлении сложных запросов с расчетом итоговых показателей разработчики нередко сталкиваются с синтаксической ошибкой: «Невозможно определить поле для записи результата». Ошибка указывает на строку в секции ИТОГИ, где выполняется приведение типов с помощью функции ВЫРАЗИТЬ() или вычисление сложных математических выражений. Рассмотрим подробнее, почему возникает данная ситуация и как правильно организовать текст запроса.
Посмотрим на пример кода, вызывающего ошибку:
Запрос.Текст = "ВЫБРАТЬ
| ЗначениеСв,
| Номенклатура,
| КоличествоПродаж,
| ЦенаРеализации
|ИЗ
| ТЧ КАК т1
|ИТОГИ
| ВЫРАЗИТЬ(СУММА(КоличествоПродаж) КАК ЧИСЛО(15, 3)),
| ВЫРАЗИТЬ(СРЕДНЕЕ(ЦенаРеализации) КАК ЧИСЛО(15, 3))
|ПО
| ЗначениеСв ИЕРАРХИЯ,
| Номенклатура";
При выполнении такого запроса платформа 1С выдает исключение при вызове метода Выполнить(), указывая на строку с ВЫРАЗИТЬ(СУММА(...)).
Проанализируем принципы работы механизма итогов в платформе 1С:
ВЫБРАТЬ полей и записи итоговых данных в соответствующие колонки результирующей выборки.ИТОГИ пишется конструкция ВЫРАЗИТЬ(СУММА(...) КАК ...) без явного псевдонима, платформа не может однозначно связать это выражение ни с одним полем из списка ВЫБРАТЬ.ИТОГИ избыточно и синтаксически не поддерживается в таком виде.ВЫБРАТЬ, платформа выдаст ошибку о невозможности расчета итогов.Разберем основной и самый надежный способ решения проблемы. Если требуется ограничить разрядность или точность чисел, конструкцию ВЫРАЗИТЬ() необходимо применить в основном списке полей выборки либо на этапе помещения данных во временную таблицу. В секции ИТОГИ следует оставить только вызов агрегатных функций (СУММА, СРЕДНЕЕ, МАКСИМУМ и др.).
Перепишем запрос следующим образом:
Запрос.Текст = "ВЫБРАТЬ
| ЗначениеСв,
| Номенклатура,
| ЦеноваяГруппа,
| ВЫРАЗИТЬ(КоличествоПродаж КАК ЧИСЛО(15, 3)) КАК КоличествоПродаж,
| ВЫРАЗИТЬ(ЦенаРеализации КАК ЧИСЛО(15, 3)) КАК ЦенаРеализации,
| ВЫРАЗИТЬ(ПолнаяСебестоимость КАК ЧИСЛО(15, 3)) КАК ПолнаяСебестоимость,
| ВЫРАЗИТЬ(Прибыль КАК ЧИСЛО(15, 3)) КАК ПрибыльЕдиницы,
| ВЫРАЗИТЬ(СуммаПрибыль КАК ЧИСЛО(15, 3)) КАК СуммаПрибыль,
| КоличествоПродажПлан КАК КоличествоПланПродаж,
| СуммаПрибыльПлан,
| Рентабельность
|ИЗ
| ТЧ КАК т1
|ИТОГИ
| МАКСИМУМ(ЦеноваяГруппа),
| СУММА(КоличествоПродаж),
| СРЕДНЕЕ(ЦенаРеализации),
| СРЕДНЕЕ(ПолнаяСебестоимость),
| СРЕДНЕЕ(ПрибыльЕдиницы),
| СУММА(СуммаПрибыль),
| СУММА(КоличествоПланПродаж),
| СУММА(СуммаПрибыльПлан),
| СУММА(Рентабельность)
|ПО
| ЗначениеСв ИЕРАРХИЯ,
| Номенклатура";
Если источником данных для временной таблицы является объект ТаблицаЗначений, передаваемый в качестве параметра, правильнее всего задать типы данных колонок еще до выполнения запроса. Для числовых полей необходимо указать объект КвалификаторыЧисла с требуемой длиной и точностью.
Рассмотрим пример правильного описания колонок таблицы значений перед выгрузкой в запрос:
КвалификаторЧисла = Новый КвалификаторыЧисла(15, 3);
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("Число"));
ОписаниеТипаЧисло = Новый ОписаниеТипов(МассивТипов, , , КвалификаторЧисла);
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура");
ТЗ.Колонки.Добавить("КоличествоПродаж", ОписаниеТипаЧисло);
ТЗ.Колонки.Добавить("ЦенаРеализации", ОписаниеТипаЧисло);
При таком подходе отпадает необходимость использовать ВЫРАЗИТЬ() как во временных таблицах, так и в секции выборки — платформа сразу создаст поля нужной разрядности.
Если в итогах требуется рассчитать сложный показатель (например, средневзвешенное значение или процент), выражению в секции ИТОГИ обязательно присваивается псевдоним, который предварительно должен быть объявлен в списке ВЫБРАТЬ.
Посмотрим на пример расчета рентабельности на уровне итогов:
Запрос.Текст = "ВЫБРАТЬ
| Номенклатура,
| СуммаВыручки,
| СуммаСебестоимости,
| 0 КАК РентабельностьПроцент
|ИЗ
| Продажи КАК Продажи
|ИТОГИ
| СУММА(СуммаВыручки),
| СУММА(СуммаСебестоимости),
| ВЫБОР
| КОГДА СУММА(СуммаСебестоимости) = 0 ТОГДА 0
| ИНАЧЕ (СУММА(СуммаВыручки) - СУММА(СуммаСебестоимости)) / СУММА(СуммаСебестоимости) * 100
| КОНЕЦ КАК РентабельностьПроцент
|ПО
| Номенклатура";
Таким образом, для устранения ошибки достаточно следовать правилу: все преобразования типов и подготовка полей выполняются в секции ВЫБРАТЬ, а в секцию ИТОГИ передаются агрегатные операции с обязательной привязкой к существующим колонкам выборки.