При разработке отчетов и аналитических выборок в системе «1С:Предприятие 8» часто возникает задача: получить в одной строке результата количество объектов, распределенных по разным категориям. Например, нам нужно одновременно узнать, сколько подано заявлений на бюджет, сколько на коммерцию и сколько по конкретным направлениям обучения. Обычное использование функции КОЛИЧЕСТВО() с условиями в ГДЕ не позволяет разделить данные на несколько колонок за один проход. Разберем, как правильно реализовать такую логику, исправим типичные ошибки и рассмотрим архитектурные рекомендации.
Это самый распространенный и эффективный способ в языке запросов 1С. Вместо того чтобы пытаться использовать функцию КОЛИЧЕСТВО, мы создаем «виртуальные» единицы для каждой интересующей нас категории. Проанализируем, как это работает: если условие для конкретной категории выполняется, запрос возвращает 1, если нет — 0. Затем мы просто суммируем эти значения.
Рассмотрим пример реализации такого запроса:
ВЫБРАТЬ
СУММА(ВЫБОР
КОГДА ПодачаЗаявлений.ПрограммаОбучения.Код В ("000000010", "000000011")
И ПодачаЗаявлений.Финансирование = &ФинансированиеКоммерция
ТОГДА 1
ИНАЧЕ 0
КОНЕЦ) КАК ППКРС_Коммерция,
СУММА(ВЫБОР
КОГДА ПодачаЗаявлений.ПрограммаОбучения.Код В ("000000001", "000000002")
И ПодачаЗаявлений.Финансирование = &ФинансированиеБюджет
ТОГДА 1
ИНАЧЕ 0
КОНЕЦ) КАК ППСЗ_Бюджет
ИЗ
РегистрНакопления.ПодачаЗаявлений КАК ПодачаЗаявлений
ГДЕ
ПодачаЗаявлений.ПриемнаяКампания = &ПриемнаяКампания
Важный момент: обратите внимание на использование оператора В (...) вместо множественных условий ИЛИ. Это не только делает код чище, но и позволяет СУБД быстрее обрабатывать фильтры. Также важно помнить, что использование И между кодами одной и той же программы (как было в исходном вопросе) — логическая ошибка, так как поле не может одновременно принимать два разных значения. Используйте только ИЛИ или В.
Иногда логика подсчета настолько сложна, что использование конструкции ВЫБОР в основном запросе делает его нечитаемым. В таких случаях мы рекомендуем использовать временные таблицы (ВТ). Сначала мы отбираем сырые данные с признаками категорий, а затем агрегируем их.
Давайте разберем этот процесс по шагам:
ВТ_Данные, где для каждой анкеты определяем её принадлежность к категории.НомерСтроки = 1).
// Шаг 1: Подготовка данных
ВЫБРАТЬ
АнкетаАбитуриента,
ВЫБОР
КОГДА ПрограммаОбучения.Код В ("000000010", "000000011") ТОГДА 1
ИНАЧЕ 0
КОНЕЦ КАК ЭтоППКРС
ПОМЕСТИТЬ ВТ_Подготовка
ИЗ
РегистрНакопления.ПодачаЗаявлений
ГДЕ
НомерСтроки = 1;
////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Итоговый подсчет
ВЫБРАТЬ
СУММА(ВТ_Подготовка.ЭтоППКРС) КАК ИтогоППКРС
ИЗ
ВТ_Подготовка КАК ВТ_Подготовка
Проанализируем производительность исходного запроса. В нем используется обращение ПодачаЗаявлений.ПрограммаОбучения.Код. В 1С это называется разыменованием ссылок. На уровне базы данных это приводит к неявному левому соединению (LEFT JOIN) с таблицей справочника программ обучения. Если записей тысячи, это существенно замедлит работу.
Как сделать лучше:
Финансирование является строкой ("Коммерческое финансирование"), это признак плохой архитектуры. Строки занимают много места и чувствительны к опечаткам. Рекомендуем использовать Перечисления. Сравнение Финансирование = ЗНАЧЕНИЕ(Перечисление.ВидыФинансирования.Бюджет) работает молниеносно.АнкетаАбитуриента.Проведен = ИСТИНА для регистра накопления чаще всего избыточно. Данные попадают в регистр только от проведенных документов. Исключение этого условия уберет еще одно лишнее соединение.Выясним причину, почему использование НомерСтроки = 1 может быть опасным. В системе 1С поле НомерСтроки является служебным. Если пользователь в табличной части документа переместит строку вверх или вниз, приоритет изменится, что может исказить отчетность.
Рекомендация: Для реализации логики приоритетов лучше добавить в регистр отдельный реквизит Приоритет с типом Число. Это обеспечит стабильность данных независимо от технических манипуляций со строками табличной части.
Также, если список кодов программ для категорий (ППКРС, ППСЗ) постоянно меняется, не стоит «зашивать» их в текст запроса. Рассмотрим более гибкий подход: добавьте в справочник ПрограммыОбучения новый реквизит (категорию) или создайте Регистр Сведений, где будет храниться соответствие программ и их типов. Тогда ваш запрос станет универсальным и не потребует вмешательства программиста при изменении классификации программ.
Итоговая схема эффективного запроса:
ВЫБОР КОГДА ... ТОГДА 1 ИНАЧЕ 0 КОНЕЦ.СУММА().&Параметр.