Как рассчитать и вывести долю стоимости и количества в запросе 1С?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При построении аналитических отчетов по продажам и отгрузкам нередко возникает задача сопоставить показатели каждой строки с общим результатом — например, рассчитать процент или долю отдельной позиции в совокупном объеме и стоимости отгрузок. Выясним причину сложности этой задачи: в языке запросов платформы 1С отсутствуют стандартные оконные функции, а секция ИТОГИ формирует иерархическую структуру выборок, что не позволяет получить итоговые суммы непосредственно в детальных записях выборки.

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

Способ 1. Расчет долей через пакет запросов и временные таблицы

Рассмотрим подробнее логику вычисления долей внутри самого запроса. Поскольку общий итог заранее неизвестен, алгоритм разделяется на три последовательных этапа:

  1. Сбор детальных данных: соединяем регистр накопления с регистром цен, рассчитываем детальную стоимость позиции (количество, умноженное на цену) и сохраняем строки во временную таблицу. Дополнительно добавляем константу связи 1 КАК КлючСвязи.
  2. Агрегация общих итогов: отдельным запросом во вторую временную таблицу сворачиваем общие суммы количества и стоимости со всего набора данных, также проставляя 1 КАК КлючСвязи.
  3. Итоговая выборка и расчет долей: соединяем детальные данные с итоговыми по общему ключу и рассчитываем процентные доли с обязательной защитой от деления на ноль.

Проанализируем также типовую ошибку при соединении с ценами. Исходное ВНУТРЕННЕЕ СОЕДИНЕНИЕ с регистром цен отсечет позиции номенклатуры, для которых не установлена цена. Чтобы не потерять расход товаров, заменим его на ЛЕВОЕ СОЕДИНЕНИЕ и применим функцию ЕСТЬNULL.

Посмотрим на полный текст пакета запросов:


ВЫБРАТЬ
    ТоварыОрганизацийОстаткиИОбороты.Склад КАК Склад,
    ТоварыОрганизацийОстаткиИОбороты.Номенклатура КАК Номенклатура,
    ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена,
    ТоварыОрганизацийОстаткиИОбороты.КоличествоРасход КАК Количество,
    ТоварыОрганизацийОстаткиИОбороты.КоличествоРасход * ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Стоимость,
    1 КАК КлючСвязи
ПОМЕСТИТЬ ВТ_Детализация
ИЗ
    РегистрНакопления.ТоварыОрганизаций.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, , ) КАК ТоварыОрганизацийОстаткиИОбороты
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ПериодЦен, ТипЦен = &ТипЦен) КАК ЦеныНоменклатурыСрезПоследних
        ПО ТоварыОрганизацийОстаткиИОбороты.Номенклатура = ЦеныНоменклатурыСрезПоследних.Номенклатура
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    СУММА(ВТ_Детализация.Количество) КАК ВсегоКоличество,
    СУММА(ВТ_Детализация.Стоимость) КАК ВсегоСтоимость,
    1 КАК КлючСвязи
ПОМЕСТИТЬ ВТ_Итоги
ИЗ
    ВТ_Детализация КАК ВТ_Детализация
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Детали.Склад КАК Склад,
    Детали.Номенклатура КАК Номенклатура,
    Детали.Цена КАК Цена,
    Детали.Количество КАК Отгрузки,
    Детали.Стоимость КАК Стоимость,
    ВЫБОР
        КОГДА ЕСТЬNULL(Итоги.ВсегоКоличество, 0) = 0
            ТОГДА 0
        ИНАЧЕ ВЫРАЗИТЬ(Детали.Количество / Итоги.ВсегоКоличество * 100 КАК ЧИСЛО(15, 2))
    КОНЕЦ КАК ДоляКоличества,
    ВЫБОР
        КОГДА ЕСТЬNULL(Итоги.ВсегоСтоимость, 0) = 0
            ТОГДА 0
        ИНАЧЕ ВЫРАЗИТЬ(Детали.Стоимость / Итоги.ВсегоСтоимость * 100 КАК ЧИСЛО(15, 2))
    КОНЕЦ КАК ДоляСтоимости
ИЗ
    ВТ_Детализация КАК Детали
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Итоги КАК Итоги
        ПО Детали.КлючСвязи = Итоги.КлючСвязи

Важные замечания по реализации:

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

Способ 2. Реализация через Систему компоновки данных (СКД)

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

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

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

Если требуется вывести поле доли с пользовательским наименованием и формулой, используем встроенный язык выражений СКД на вкладке Вычисляемые поля или в выражении ресурса:

Сумма(Стоимость) / ВычислитьВыражение("Сумма(Стоимость)", "") * 100

В этой формуле второй параметр "" (пустая строка) указывает функции ВычислитьВыражение на то, что суммирование необходимо производить по общему итогу всего отчета. Аналогично рассчитывается и процент по количеству позиций.

← На главную