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