Как подсчитать общее количество документов в запросе 1С с группировкой по менеджерам?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов и обработок в платформе 1С часто возникает задача: вывести количество документов по каждому ответственному менеджеру и одновременно получить итоговое (общее) количество документов за указанный период.

Сложность заключается в том, что в языке запросов 1С отсутствуют оконные (аналитические) функции вроде OVER(), которые в классических СУБД позволяют выводить общее значение агрегата в каждой строке сгруппированного запроса. Рассмотрим подробнее основные способы решения этой задачи в зависимости от ваших целей.

Способ 1. Использование секции ИТОГИ ПО ОБЩИЕ

Если запрос выполняется непосредственно из кода 1С для последующей обработки выборки или вывода в документ, наиболее простым решением является применение конструкции ИТОГИ ПО ОБЩИЕ.

Проанализируем пример такого запроса:


ВЫБРАТЬ
    ЗаказКлиента.Менеджер КАК Менеджер,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ЗаказКлиента.Ссылка) КАК КоличествоЗаказов
ИЗ
    Документ.ЗаказКлиента КАК ЗаказКлиента
ГДЕ
    ЗаказКлиента.Дата МЕЖДУ &НачДата И &КонДата
СГРУППИРОВАТЬ ПО
    ЗаказКлиента.Менеджер
ИТОГИ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ КоличествоЗаказов)
ПО
    ОБЩИЕ,
    Менеджер

Особенности данного подхода:

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

Способ 2. Использование пакетного запроса с временной таблицей (Соединение ПО ИСТИНА)

Если вам требуется добавить поле с общим количеством документов к каждой строке сгруппированного результата (например, для последующего соединения с другими таблицами в пакете запросов), разберем по шагам правильную структуру пакетного запроса.

Сначала сформируем временную таблицу, рассчитав общее количество уникальных документов с учетом отборов по дате:


ВЫБРАТЬ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ЗаказКлиента.Ссылка) КАК ОбщийИтогДокументов
ПОМЕСТИТЬ ВТ_ОбщийИтог
ИЗ
    Документ.ЗаказКлиента КАК ЗаказКлиента
ГДЕ
    ЗаказКлиента.Дата МЕЖДУ &НачДата И &КонДата
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ЗаказКлиента.Менеджер КАК Менеджер,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ЗаказКлиента.Ссылка) КАК КоличествоЗаказовМенеджера,
    ВТ_ОбщийИтог.ОбщийИтогДокументов КАК ВсегоДокументов
ИЗ
    Документ.ЗаказКлиента КАК ЗаказКлиента
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ОбщийИтог КАК ВТ_ОбщийИтог
        ПО ИСТИНА
ГДЕ
    ЗаказКлиента.Дата МЕЖДУ &НачДата И &КонДата
СГРУППИРОВАТЬ ПО
    ЗаказКлиента.Менеджер,
    ВТ_ОбщийИтог.ОбщийИтогДокументов

Рассмотрим, как работает данная схема:

  1. Первый запрос рассчитывает ровно одну строку с полем ОбщийИтогДокументов и помещает её в ВТ_ОбщийИтог.
  2. Во втором запросе выполняется группировка по менеджерам, а таблица ВТ_ОбщийИтог присоединяется по условию ПО ИСТИНА (без указания ключевых полей связи). Это позволяет добавить итоговое число в каждую строчку результата.

Способ 3. Пакетный запрос с раздельным получением результатов

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

Посмотрим на пример структуры пакета:


ВЫБРАТЬ
    ЗаказКлиента.Менеджер КАК Менеджер,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ЗаказКлиента.Ссылка) КАК КоличествоЗаказов
ИЗ
    Документ.ЗаказКлиента КАК ЗаказКлиента
ГДЕ
    ЗаказКлиента.Дата МЕЖДУ &НачДата И &КонДата
СГРУППИРОВАТЬ ПО
    ЗаказКлиента.Менеджер
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ЗаказКлиента.Ссылка) КАК ВсегоДокументов
ИЗ
    Документ.ЗаказКлиента КАК ЗаказКлиента
ГДЕ
    ЗаказКлиента.Дата МЕЖДУ &НачДата И &КонДата

В коде модуля 1С обработка результатов выполняется следующим образом:


РезультатыПакет = Запрос.ВыполнитьПакет();

// Выборка по менеджерам
ВыборкаМенеджеры = РезультатыПакет[0].Выбрать();
Пока ВыборкаМенеджеры.Следующий() Цикл
    // Обработка строк по менеджерам
КонецЦикла;

// Получение общего количества
ВыборкаИтог = РезультатыПакет[1].Выбрать();
Если ВыборкаИтог.Следующий() Тогда
    ОбщееКоличество = ВыборкаИтог.ВсегоДокументов;
КонецЕсли;

Важные рекомендации и частые ошибки

← На главную