Как в запросе 1С правильно сгруппировать данные по ставкам НДС и посчитать их количество?

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

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

Анализируем проблему: почему КОЛИЧЕСТВО(РАЗЛИЧНЫЕ) выдает единицу?

Рассмотрим ситуацию, с которой столкнулся автор темы. В коде запроса была использована конструкция:

КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ПоступлениеТоваров.СтавкаНДС) КАК СтавкаНДС

Проанализируем, что происходит на уровне СУБД при выполнении такой команды. Функция КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) работает в два этапа:

  1. Система выбирает все уникальные значения из указанного поля в рамках выборки.
  2. Система подсчитывает количество этих уникальных значений.

Если в вашем документе "Поступление товаров" есть 10 строк, и во всех десяти строках указана ставка "20%", то уникальное значение всего одно — "20%". Следовательно, функция вернет число 1. Это не значит, что система "конвертировала ставку в цифру", как предположил автор. Это значит, что функция честно выполнила свою задачу — посчитала количество уникальных элементов.

Если ваша задача — увидеть, какие именно ставки использованы (например, 10% и 20%) и сколько раз каждая из них встречается, использование функции КОЛИЧЕСТВО(РАЗЛИЧНЫЕ) в поле выбора является ошибкой, так как она "схлопывает" данные до одного итогового числа.

Правильное решение: использование группировки

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

Разберем пример кода, который решает задачу:


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

В данном примере мы выполнили следующие действия:

Расширенная аналитика: Использование итогов

Иногда требуется получить одновременно и детальные данные по каждой ставке, и общее количество различных ставок в документе. В этом случае нам поможет секция ИТОГИ. Посмотрим на пример ситуации, когда нам нужно свернуть данные в итоговой строке:


ВЫБРАТЬ
    ПоступлениеТоваровТовары.Ссылка КАК Ссылка,
    ПоступлениеТоваровТовары.СтавкаНДС КАК СтавкаНДС,
    СУММА(ПоступлениеТоваровТовары.Сумма) КАК Сумма
ИЗ
    Документ.ПоступлениеТоваров.Товары КАК ПоступлениеТоваровТовары
СГРУППИРОВАТЬ ПО
    ПоступлениеТоваровТовары.Ссылка,
    ПоступлениеТоваровТовары.СтавкаНДС
ИТОГИ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ СтавкаНДС)
ПО
    Ссылка

Проанализируем этот запрос. Он вернет дерево значений, где на верхнем уровне (в иерархии по ссылке документа) в поле количества будет стоять число уникальных ставок в этом документе, а ниже будут расположены строки с конкретными ставками и суммами по ним. Это именно то, что часто требуется для формирования сложных отчетов или вывода итогов в подвал формы.

Важные технические нюансы

При работе со ставками НДС в 1С следует учитывать несколько технических аспектов, которые влияют на результат запроса:

  1. Тип данных: В современных конфигурациях (на базе БСП, таких как ERP, УТ 11 или БП 3.0) СтавкаНДС может быть либо Справочником, либо Перечислением. Если это Справочник, помните, что пустые значения (незаполненная ставка) в запросе будут интерпретироваться как NULL или пустая ссылка. Функция КОЛИЧЕСТВО(Поле) игнорирует значения NULL, поэтому такие строки не попадут в подсчет, если не использовать КОЛИЧЕСТВО(*).
  2. Производительность: Использование ключевого слова РАЗЛИЧНЫЕ внутри функции КОЛИЧЕСТВО создает дополнительную нагрузку на СУБД, так как требует сортировки данных для исключения дублей. На масштабе одного документа это незаметно, но при анализе миллионов записей в регистрах накопления это может замедлить выполнение отчета.
  3. Свертка таблицы значений: Если вы уже получили данные в Таблицу Значений (ТЗ) и хотите "сгруппировать их одним запросом", как упоминал автор темы, рассмотрите возможность использования временных таблиц. Вы можете поместить вашу ТЗ во временную таблицу и выполнить к ней запрос с группировкой — это гораздо эффективнее, чем ручной перебор строк в цикле.

Подводя итог, можно сказать: если вам нужно увидеть состав (какие бывают ставки), используйте СГРУППИРОВАТЬ ПО. Если вам нужно получить число (сколько всего уникальных видов ставок), используйте КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...). Совмещение этих подходов через ИТОГИ дает наиболее полную картину данных.

← На главную