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