Как в СКД посчитать количество партнеров с продажами выше определенной суммы?

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

В процессе разработки отчетов в Системе компоновки данных (СКД) часто возникает задача, которая ставит в тупик даже опытных разработчиков: как посчитать количество уникальных записей по условию, которое само основано на агрегированной величине? Классический пример — найти количество клиентов, сумма продаж по которым за период превысила заданный порог.

Проанализируем типичную ситуацию. У нас есть отчет по продажам с полями Менеджер, Партнер, Заказ, СуммаВыручки. Нам нужно вывести в итогах отчета общее количество партнеров, у которых сумма выручки за период, например, больше или равна 100 000 рублей.

Интуитивная попытка решить это "в лоб" в вычисляемом поле ресурса выглядит так:


ВЫБОР
    КОГДА Сумма(СуммаВыручки) >= 100000
        ТОГДА Количество(РАЗЛИЧНЫЕ Партнер)
КОНЕЦ

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

Давайте разберем два правильных и эффективных способа решения этой задачи.

Решение 1: Предварительная подготовка данных в запросе с помощью `ИМЕЮЩИЕ` (HAVING)

Этот метод считается классическим и наиболее производительным, поскольку вся сложная логика отбора данных переносится на уровень базы данных (СУБД), которая для таких задач и предназначена. Суть метода — подготовить набор данных, который уже содержит только нужных нам партнеров, и затем в основном запросе просто посчитать их количество.

Разберем по шагам:

  1. Создаем вложенный запрос или временную таблицу.
  2. В этом запросе мы группируем данные по полю Партнер и считаем для каждого из них общую сумму выручки.
  3. С помощью оператора ИМЕЮЩИЕ (аналог ГДЕ, но для агрегированных данных) мы отфильтровываем результат, оставляя только тех партнеров, у которых итоговая сумма выручки удовлетворяет нашему условию (>= 100000).
  4. Основной запрос СКД обращается к этой уже отфильтрованной таблице и просто считает количество уникальных партнеров.

Посмотрим на примерную структуру запроса. Допустим, у нас есть регистр накопления Продажи.


ВЫБРАТЬ
    ПродажиОтфильтрованные.Партнер,
    ПродажиОтфильтрованные.СуммаВыручки,
    // Другие поля из основного набора данных
ИЗ
    (ВЫБРАТЬ
        ПродажиОбороты.Партнер КАК Партнер,
        СУММА(ПродажиОбороты.СуммаВыручки) КАК СуммаВыручки
    ИЗ
        РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ПродажиОбороты
    
    СГРУППИРОВАТЬ ПО
        ПродажиОбороты.Партнер
    
    ИМЕЮЩИЕ
        СУММА(ПродажиОбороты.СуммаВыручки) >= 100000) КАК ПродажиОтфильтрованные
// Здесь можно соединить с другими таблицами для получения остальных полей отчета
// ...

Теперь в ресурсах отчета достаточно будет указать простое выражение: Количество(Различные Партнер). Оно будет применено к уже отфильтрованному набору данных и даст корректный результат.

Преимущества:

Недостатки:

Решение 2: Использование функции `ВычислитьВыражениеСГруппировкойМассив`

Это более гибкий и современный способ, который позволяет реализовать сложную логику непосредственно в настройках отчета, не затрагивая основной запрос. Он идеально подходит, когда нужно добавить подобный расчет в уже существующий отчет "на лету".

В этом методе мы используем мощную функцию СКД ВычислитьВыражениеСГруппировкойМассив(). Разберем, как она работает.

Для поля-ресурса, которое должно считать наших партнеров, нужно написать следующее выражение:


Сумма(ВычислитьВыражениеСГруппировкойМассив("ВЫБОР КОГДА Сумма(СуммаВыручки) >= 100000 ТОГДА 1 ИНАЧЕ 0 КОНЕЦ", "Партнер"))

Давайте проанализируем эту конструкцию изнутри наружу:

  1. "ВЫБОР КОГДА Сумма(СуммаВыручки) >= 100000 ТОГДА 1 ИНАЧЕ 0 КОНЕЦ" — это выражение, которое мы хотим вычислить. Обратите внимание, оно записано как строка.
  2. "Партнер" — это строка с именем группировки, в контексте которой будет вычисляться первое выражение. СКД сгруппирует все записи по партнерам.
  3. ВычислитьВыражениеСГруппировкойМассив(...) — эта функция делает "магию". Она выполняет следующие действия:
    • Берет все детальные записи отчета.
    • Группирует их по полю Партнер.
    • Для каждой такой группы (т.е. для каждого уникального партнера) она вычисляет выражение из первого параметра. Если у партнера сумма продаж больше или равна 100 000, результатом для него будет 1. Если меньше — 0.
    • В итоге функция возвращает массив из этих единиц и нулей. Например: `[1, 0, 0, 1, 1, ...]`, где каждый элемент соответствует одному партнеру.
  4. Сумма(...) — это внешняя, обычная агрегатная функция. Она применяется к результату работы внутренней функции, то есть к массиву. Она просто суммирует все элементы массива (1 + 0 + 0 + 1 + 1 + ...), и в итоге мы получаем общее количество партнеров, для которых условие выполнилось.

Этот метод элегантен, так как позволяет обойти ограничение на вложенные агрегаты, выполняя агрегацию в два этапа: сначала внутри функции для каждой группы, а затем снаружи над результатом.

Преимущества:

Недостатки:

Итоги и рекомендации

Мы рассмотрели два мощных способа решения задачи подсчета по агрегатному условию. Выбор между ними зависит от ваших приоритетов:

Оба подхода являются штатными и правильными инструментами СКД, и знание их обоих позволит вам эффективно решать самые нетривиальные задачи при построении аналитической отчетности в 1С.

← На главную