Как эффективно посчитать количество объектов по различным условиям в одном запросе 1С

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

При разработке отчетов и аналитических выборок в системе «1С:Предприятие 8» часто возникает задача: получить в одной строке результата количество объектов, распределенных по разным категориям. Например, нам нужно одновременно узнать, сколько подано заявлений на бюджет, сколько на коммерцию и сколько по конкретным направлениям обучения. Обычное использование функции КОЛИЧЕСТВО() с условиями в ГДЕ не позволяет разделить данные на несколько колонок за один проход. Разберем, как правильно реализовать такую логику, исправим типичные ошибки и рассмотрим архитектурные рекомендации.

Метод 1. Использование функции СУММА с конструкцией ВЫБОР

Это самый распространенный и эффективный способ в языке запросов 1С. Вместо того чтобы пытаться использовать функцию КОЛИЧЕСТВО, мы создаем «виртуальные» единицы для каждой интересующей нас категории. Проанализируем, как это работает: если условие для конкретной категории выполняется, запрос возвращает 1, если нет — 0. Затем мы просто суммируем эти значения.

Рассмотрим пример реализации такого запроса:


ВЫБРАТЬ
    СУММА(ВЫБОР
            КОГДА ПодачаЗаявлений.ПрограммаОбучения.Код В ("000000010", "000000011") 
                И ПодачаЗаявлений.Финансирование = &ФинансированиеКоммерция
                ТОГДА 1
            ИНАЧЕ 0
        КОНЕЦ) КАК ППКРС_Коммерция,
    
    СУММА(ВЫБОР
            КОГДА ПодачаЗаявлений.ПрограммаОбучения.Код В ("000000001", "000000002") 
                И ПодачаЗаявлений.Финансирование = &ФинансированиеБюджет
                ТОГДА 1
            ИНАЧЕ 0
        КОНЕЦ) КАК ППСЗ_Бюджет
ИЗ
    РегистрНакопления.ПодачаЗаявлений КАК ПодачаЗаявлений
ГДЕ
    ПодачаЗаявлений.ПриемнаяКампания = &ПриемнаяКампания

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

Метод 2. Группировка во временных таблицах

Иногда логика подсчета настолько сложна, что использование конструкции ВЫБОР в основном запросе делает его нечитаемым. В таких случаях мы рекомендуем использовать временные таблицы (ВТ). Сначала мы отбираем сырые данные с признаками категорий, а затем агрегируем их.

Давайте разберем этот процесс по шагам:

  1. Создаем временную таблицу ВТ_Данные, где для каждой анкеты определяем её принадлежность к категории.
  2. В этой же таблице можно сразу отсечь лишние записи, например, оставить только первые приоритеты (НомерСтроки = 1).
  3. Во втором запросе пакета выполняем итоговое суммирование.

// Шаг 1: Подготовка данных
ВЫБРАТЬ
    АнкетаАбитуриента,
    ВЫБОР
        КОГДА ПрограммаОбучения.Код В ("000000010", "000000011") ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ КАК ЭтоППКРС
ПОМЕСТИТЬ ВТ_Подготовка
ИЗ
    РегистрНакопления.ПодачаЗаявлений
ГДЕ
    НомерСтроки = 1;

////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Итоговый подсчет
ВЫБРАТЬ
    СУММА(ВТ_Подготовка.ЭтоППКРС) КАК ИтогоППКРС
ИЗ
    ВТ_Подготовка КАК ВТ_Подготовка

Оптимизация: работа с типами данных и ссылками

Проанализируем производительность исходного запроса. В нем используется обращение ПодачаЗаявлений.ПрограммаОбучения.Код. В 1С это называется разыменованием ссылок. На уровне базы данных это приводит к неявному левому соединению (LEFT JOIN) с таблицей справочника программ обучения. Если записей тысячи, это существенно замедлит работу.

Как сделать лучше:

Уточнение по архитектуре: приоритеты и категории

Выясним причину, почему использование НомерСтроки = 1 может быть опасным. В системе 1С поле НомерСтроки является служебным. Если пользователь в табличной части документа переместит строку вверх или вниз, приоритет изменится, что может исказить отчетность.

Рекомендация: Для реализации логики приоритетов лучше добавить в регистр отдельный реквизит Приоритет с типом Число. Это обеспечит стабильность данных независимо от технических манипуляций со строками табличной части.

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

Итоговая схема эффективного запроса:

  1. Используйте ВЫБОР КОГДА ... ТОГДА 1 ИНАЧЕ 0 КОНЕЦ.
  2. Оберните этот выбор в функцию СУММА().
  3. Сгруппируйте результат, если нужно получить данные в разрезе других измерений (например, подразделений).
  4. Передавайте списки условий (коды, программы) через параметры запроса &Параметр.
← На главную