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