В практике разработки на платформе 1С часто возникают задачи, когда стандартная функция КОЛИЧЕСТВО(*) не дает нужного результата. Например, когда необходимо посчитать количество уникальных должностей, но при этом учесть сотрудников, у которых должность не указана, как отдельные уникальные единицы. Рассмотрим подробнее, как реализовать такой «хитрый» подсчет с помощью языка запросов и системы компоновки данных (СКД).
Представим ситуацию: в табличной части документа есть колонки Сотрудник и Должность. Нам нужно получить итоговое число по следующему алгоритму:
Проанализируем пример: если у нас есть два записи с «Должность1» и три записи с пустыми должностями для разных сотрудников, итоговый результат должен быть 4 (1 уникальная должность + 3 уникальных сотрудника без должностей).
Разберем наиболее эффективный способ решения задачи «в лоб» через основной запрос. Основная идея заключается в том, чтобы привести анализируемые данные к единому полю, по которому затем можно будет выполнить группировку или подсчет различных значений. Выясним причину, почему обычное КОЛИЧЕСТВО(Должность) не подходит: оно просто посчитает все заполненные значения, игнорируя логику уникальности сотрудников без должностей.
Рассмотрим пример кода, который объединяет логику проверки на пустую ссылку:
ВЫБРАТЬ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВЫБОР
КОГДА ТабЧасть.Должность = ЗНАЧЕНИЕ(Справочник.Должность.ПустаяСсылка)
ТОГДА ТабЧасть.Сотрудник
ИНАЧЕ ТабЧасть.Должность
КОНЕЦ) КАК ХитроеКоличество
ИЗ
Документ.Пример.ТабличнаяЧасть1 КАК ТабЧасть
ГДЕ
ТабЧасть.Ссылка = &Ссылка
В этом примере мы создаем виртуальное поле прямо «на лету». Если должность пуста, система подставляет в расчет сотрудника, если заполнена — саму должность. Функция КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) затем корректно сворачивает одинаковые должности и уникально считает сотрудников без них.
Если логика еще сложнее (например, нужно считать уникальные пары Сотрудник + Должность, но при этом по-особому обрабатывать пустые значения), лучше использовать вложенный запрос. Это позволит сначала подготовить «чистые» данные, а затем выполнить итоговый агрегатный расчет.
Разберем по шагам этот метод:
РАЗЛИЧНЫЕ комбинации нужных нам полей.
ВЫБРАТЬ
КОЛИЧЕСТВО(*) КАК ИтоговоеКоличество
ИЗ
(ВЫБРАТЬ РАЗЛИЧНЫЕ
ТабЧасть.Сотрудник КАК Сотрудник,
ТабЧасть.Должность КАК Должность
ИЗ
Документ.Пример.ТабличнаяЧасть1 КАК ТабЧасть
ГДЕ
ТабЧасть.Ссылка = &Ссылка) КАК ВложенныйЗапрос
Важный момент: такой подход удобен тем, что внутри вложенного запроса вы можете наложить любые дополнительные фильтры (например, ГДЕ НЕ Сотрудник.ПометкаУдаления).
Проанализируем ситуацию, когда нам нужно не просто общее число, а количество записей в разрезе какого-либо объекта (например, документа или версии объекта). В этом случае мы используем предложение СГРУППИРОВАТЬ ПО.
ВЫБРАТЬ
ВерсииОбъектов.Объект КАК Объект,
КОЛИЧЕСТВО(ВерсииОбъектов.Объект) КАК КоличествоВерсий
ИЗ
РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
ГДЕ
ВерсииОбъектов.ДатаВерсии > &ДатаНачала
СГРУППИРОВАТЬ ПО
ВерсииОбъектов.Объект
УПОРЯДОЧИТЬ ПО
КоличествоВерсий УБЫВ
В данном примере мы видим, как система подсчитывает количество вхождений для каждого уникального объекта. Это полезно, когда задача стоит не «сколько строк всего», а «сколько строк принадлежит каждому владельцу».
Посмотрим на технические нюансы, которые часто путают начинающих разработчиков. В 1С есть разница между NULL (отсутствие значения в базе) и пустой ссылкой ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка).
Функция КОЛИЧЕСТВО(Поле) ведет себя следующим образом:
NULL, оно не учитывается в подсчете.Чтобы исключить пустые ссылки из подсчета, их нужно принудительно превратить в NULL внутри запроса:
ВЫБРАТЬ
КОЛИЧЕСТВО(ВЫБОР
КОГДА Должность = ЗНАЧЕНИЕ(Справочник.Должности.ПустаяСсылка)
ТОГДА NULL
ИНАЧЕ Должность
КОНЕЦ) КАК КоличествоЗаполненныхДолжностей
ИЗ
...
Если ваша задача реализуется в рамках отчета, то «хитрый» подсчет можно вынести на уровень ресурсов СКД. Это зачастую проще, чем писать сложные вложенные запросы.
В СКД на закладке «Ресурсы» вы можете использовать выражение:
Количество(Различные Должность) + Количество(Различные Сотрудник)
Однако будьте осторожны: СКД суммирует эти показатели по-своему. Для более точного контроля лучше создать Вычисляемое поле с логикой ВЫБОР КОГДА, описанной в первом решении, и уже его добавлять в ресурсы как Количество(Различные ВычисляемоеПоле).
Подводя итог, можно сказать, что универсального метода «одной кнопкой» для хитрых расчетов не существует, но комбинация ВЫБОР и ГРУППИРОВКА решает 99% задач. При работе с большими таблицами, такими как РегистрСведений.ВерсииОбъектов, всегда помните о производительности: использование РАЗЛИЧНЫЕ на миллионах строк может существенно замедлить работу системы. Всегда старайтесь ограничивать выборку по индексированным полям (период, объект, тип).