Как в запросе 1С подсчитать количество строк по сложным условиям?

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

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

Анализ задачи и логики подсчета

Представим ситуацию: в табличной части документа есть колонки Сотрудник и Должность. Нам нужно получить итоговое число по следующему алгоритму:

  1. Если у сотрудника заполнена должность, мы должны считать уникальные вхождения комбинаций.
  2. Если должность пустая, каждый такой сотрудник должен считаться как отдельная строка.
  3. Дублирующиеся строки (один и тот же сотрудник на той же должности) должны игнорироваться или сворачиваться в зависимости от бизнес-логики.

Проанализируем пример: если у нас есть два записи с «Должность1» и три записи с пустыми должностями для разных сотрудников, итоговый результат должен быть 4 (1 уникальная должность + 3 уникальных сотрудника без должностей).

Решение №1: Использование конструкции ВЫБОР КОГДА в запросе

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

Рассмотрим пример кода, который объединяет логику проверки на пустую ссылку:


ВЫБРАТЬ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВЫБОР
            КОГДА ТабЧасть.Должность = ЗНАЧЕНИЕ(Справочник.Должность.ПустаяСсылка)
                ТОГДА ТабЧасть.Сотрудник
            ИНАЧЕ ТабЧасть.Должность
        КОНЕЦ) КАК ХитроеКоличество
ИЗ
    Документ.Пример.ТабличнаяЧасть1 КАК ТабЧасть
ГДЕ
    ТабЧасть.Ссылка = &Ссылка

В этом примере мы создаем виртуальное поле прямо «на лету». Если должность пуста, система подставляет в расчет сотрудника, если заполнена — саму должность. Функция КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) затем корректно сворачивает одинаковые должности и уникально считает сотрудников без них.

Решение №2: Использование вложенных запросов для сложных связок

Если логика еще сложнее (например, нужно считать уникальные пары Сотрудник + Должность, но при этом по-особому обрабатывать пустые значения), лучше использовать вложенный запрос. Это позволит сначала подготовить «чистые» данные, а затем выполнить итоговый агрегатный расчет.

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

  1. Во вложенном запросе выберем РАЗЛИЧНЫЕ комбинации нужных нам полей.
  2. Во внешнем запросе просто посчитаем количество строк, полученных из вложенного запроса.

ВЫБРАТЬ
    КОЛИЧЕСТВО(*) КАК ИтоговоеКоличество
ИЗ
    (ВЫБРАТЬ РАЗЛИЧНЫЕ
        ТабЧасть.Сотрудник КАК Сотрудник,
        ТабЧасть.Должность КАК Должность
    ИЗ
        Документ.Пример.ТабличнаяЧасть1 КАК ТабЧасть
    ГДЕ
        ТабЧасть.Ссылка = &Ссылка) КАК ВложенныйЗапрос

Важный момент: такой подход удобен тем, что внутри вложенного запроса вы можете наложить любые дополнительные фильтры (например, ГДЕ НЕ Сотрудник.ПометкаУдаления).

Решение №3: Подсчет через группировку (GROUP BY)

Проанализируем ситуацию, когда нам нужно не просто общее число, а количество записей в разрезе какого-либо объекта (например, документа или версии объекта). В этом случае мы используем предложение СГРУППИРОВАТЬ ПО.


ВЫБРАТЬ
    ВерсииОбъектов.Объект КАК Объект,
    КОЛИЧЕСТВО(ВерсииОбъектов.Объект) КАК КоличествоВерсий
ИЗ
    РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
ГДЕ
    ВерсииОбъектов.ДатаВерсии > &ДатаНачала
СГРУППИРОВАТЬ ПО
    ВерсииОбъектов.Объект
УПОРЯДОЧИТЬ ПО
    КоличествоВерсий УБЫВ

В данном примере мы видим, как система подсчитывает количество вхождений для каждого уникального объекта. Это полезно, когда задача стоит не «сколько строк всего», а «сколько строк принадлежит каждому владельцу».

Особенности работы с NULL и пустыми ссылками

Посмотрим на технические нюансы, которые часто путают начинающих разработчиков. В 1С есть разница между NULL (отсутствие значения в базе) и пустой ссылкой ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка).

Функция КОЛИЧЕСТВО(Поле) ведет себя следующим образом:

Чтобы исключить пустые ссылки из подсчета, их нужно принудительно превратить в NULL внутри запроса:


ВЫБРАТЬ
    КОЛИЧЕСТВО(ВЫБОР
            КОГДА Должность = ЗНАЧЕНИЕ(Справочник.Должности.ПустаяСсылка)
                ТОГДА NULL
            ИНАЧЕ Должность
        КОНЕЦ) КАК КоличествоЗаполненныхДолжностей
ИЗ
    ...

Реализация в СКД (Система компоновки данных)

Если ваша задача реализуется в рамках отчета, то «хитрый» подсчет можно вынести на уровень ресурсов СКД. Это зачастую проще, чем писать сложные вложенные запросы.

В СКД на закладке «Ресурсы» вы можете использовать выражение:

Количество(Различные Должность) + Количество(Различные Сотрудник)

Однако будьте осторожны: СКД суммирует эти показатели по-своему. Для более точного контроля лучше создать Вычисляемое поле с логикой ВЫБОР КОГДА, описанной в первом решении, и уже его добавлять в ресурсы как Количество(Различные ВычисляемоеПоле).

Резюме и рекомендации

Подводя итог, можно сказать, что универсального метода «одной кнопкой» для хитрых расчетов не существует, но комбинация ВЫБОР и ГРУППИРОВКА решает 99% задач. При работе с большими таблицами, такими как РегистрСведений.ВерсииОбъектов, всегда помните о производительности: использование РАЗЛИЧНЫЕ на миллионах строк может существенно замедлить работу системы. Всегда старайтесь ограничивать выборку по индексированным полям (период, объект, тип).

← На главную